CWiiSaveCrypted::CWiiSaveCrypted(const char* FileName, u64 TitleID) : m_TitleID(TitleID) { Common::ReadReplacements(replacements); strcpy(pathData_bin, FileName); memcpy(SD_IV, "\x21\x67\x12\xE6\xAA\x1F\x68\x9F\x95\xC5\xA2\x23\x24\xDC\x6A\x98", 0x10); if (!TitleID) // Import { AES_set_decrypt_key(SDKey, 128, &m_AES_KEY); do { b_valid = true; ReadHDR(); ReadBKHDR(); ImportWiiSaveFiles(); // TODO: check_sig() if (b_valid) { SuccessAlertT("Successfully imported save files"); b_tryAgain = false; } else { b_tryAgain = AskYesNoT("Import failed, try again?"); } } while(b_tryAgain); } else { AES_set_encrypt_key(SDKey, 128, &m_AES_KEY); if (getPaths(true)) { do { b_valid = true; WriteHDR(); WriteBKHDR(); ExportWiiSaveFiles(); do_sig(); if (b_valid) { SuccessAlertT("Successfully exported file to %s", pathData_bin); b_tryAgain = false; } else { b_tryAgain = AskYesNoT("Export failed, try again?"); } } while(b_tryAgain); } } }
// Display and Interface settings void CConfigMain::DisplaySettingsChanged(wxCommandEvent& event) { switch (event.GetId()) { // Display - Interface case ID_INTERFACE_CONFIRMSTOP: SConfig::GetInstance().m_LocalCoreStartupParameter.bConfirmStop = ConfirmStop->IsChecked(); break; case ID_INTERFACE_USEPANICHANDLERS: SConfig::GetInstance().m_LocalCoreStartupParameter.bUsePanicHandlers = UsePanicHandlers->IsChecked(); SetEnableAlert(UsePanicHandlers->IsChecked()); break; case ID_INTERFACE_ONSCREENDISPLAYMESSAGES: SConfig::GetInstance().m_LocalCoreStartupParameter.bOnScreenDisplayMessages = OnScreenDisplayMessages->IsChecked(); SetEnableAlert(OnScreenDisplayMessages->IsChecked()); break; case ID_INTERFACE_LANG: if (SConfig::GetInstance().m_InterfaceLanguage != langIds[InterfaceLang->GetSelection()]) SuccessAlertT("You must restart Dolphin in order for the change to take effect."); SConfig::GetInstance().m_InterfaceLanguage = langIds[InterfaceLang->GetSelection()]; break; case ID_HOTKEY_CONFIG: { HotkeyConfigDialog m_HotkeyDialog(this); m_HotkeyDialog.ShowModal(); } // Update the GUI in case menu accelerators were changed main_frame->UpdateGUI(); break; } }
void InterfaceConfigPane::OnInterfaceLanguageChoiceChanged(wxCommandEvent& event) { if (SConfig::GetInstance().m_InterfaceLanguage != language_ids[m_interface_lang_choice->GetSelection()]) SuccessAlertT("You must restart Dolphin in order for the change to take effect."); SConfig::GetInstance().m_InterfaceLanguage = language_ids[m_interface_lang_choice->GetSelection()]; }
void CWiiSaveCrypted::ExportAllSaves() { std::string titleFolder = File::GetUserPath(D_WIIUSER_IDX) + "title"; std::vector<u64> titles; u32 pathMask = 0x00010000; for (int i = 0; i < 8; ++i) { File::FSTEntry FST_Temp; std::string folder = StringFromFormat("%s/%08x/", titleFolder.c_str(), pathMask | i); File::ScanDirectoryTree(folder, FST_Temp); for (const File::FSTEntry& entry : FST_Temp.children) { if (entry.isDirectory) { u32 gameid; if (AsciiToHex(entry.virtualName, gameid)) { std::string bannerPath = StringFromFormat("%s%08x/data/banner.bin", folder.c_str(), gameid); if (File::Exists(bannerPath)) { u64 titleID = (((u64)pathMask | i) << 32) | gameid; titles.push_back(titleID); } } } } } SuccessAlertT("Found %x save files", (unsigned int) titles.size()); for (const u64& title : titles) { CWiiSaveCrypted* exportSave = new CWiiSaveCrypted("", title); delete exportSave; } }
CWiiSaveCrypted::CWiiSaveCrypted(const char* FileName, u64 TitleID) : m_TitleID(TitleID) { Common::ReadReplacements(replacements); encryptedSavePath = std::string(FileName); memcpy(SD_IV, "\x21\x67\x12\xE6\xAA\x1F\x68\x9F\x95\xC5\xA2\x23\x24\xDC\x6A\x98", 0x10); if (!TitleID) // Import { aes_setkey_dec(&m_AES_ctx, SDKey, 128); b_valid = true; ReadHDR(); ReadBKHDR(); ImportWiiSaveFiles(); // TODO: check_sig() if (b_valid) { SuccessAlertT("Successfully imported save files"); } else { PanicAlertT("Import failed"); } } else { aes_setkey_enc(&m_AES_ctx, SDKey, 128); if (getPaths(true)) { b_valid = true; WriteHDR(); WriteBKHDR(); ExportWiiSaveFiles(); do_sig(); if (b_valid) { SuccessAlertT("Successfully exported file to %s", encryptedSavePath.c_str()); } else { PanicAlertT("Export failed"); } } } }
bool SCoreStartupParameter::AutoSetup(EBootBS2 _BootBS2) { std::string Region(EUR_DIR); switch (_BootBS2) { case BOOT_DEFAULT: { bool bootDrive = cdio_is_cdrom(m_strFilename); // Check if the file exist, we may have gotten it from a --elf command line // that gave an incorrect file name if (!bootDrive && !File::Exists(m_strFilename)) { PanicAlertT("The specified file \"%s\" does not exist", m_strFilename.c_str()); return false; } std::string Extension; SplitPath(m_strFilename, nullptr, nullptr, &Extension); if (!strcasecmp(Extension.c_str(), ".gcm") || !strcasecmp(Extension.c_str(), ".iso") || !strcasecmp(Extension.c_str(), ".wbfs") || !strcasecmp(Extension.c_str(), ".ciso") || !strcasecmp(Extension.c_str(), ".gcz") || bootDrive) { m_BootType = BOOT_ISO; std::unique_ptr<DiscIO::IVolume> pVolume(DiscIO::CreateVolumeFromFilename(m_strFilename)); if (pVolume == nullptr) { if (bootDrive) PanicAlertT("Could not read \"%s\". " "There is no disc in the drive, or it is not a GC/Wii backup. " "Please note that original GameCube and Wii discs cannot be read " "by most PC DVD drives.", m_strFilename.c_str()); else PanicAlertT("\"%s\" is an invalid GCM/ISO file, or is not a GC/Wii ISO.", m_strFilename.c_str()); return false; } m_strName = pVolume->GetName(); m_strUniqueID = pVolume->GetUniqueID(); m_strRevisionSpecificUniqueID = pVolume->GetRevisionSpecificUniqueID(); // Check if we have a Wii disc bWii = DiscIO::IsVolumeWiiDisc(pVolume.get()); switch (pVolume->GetCountry()) { case DiscIO::IVolume::COUNTRY_USA: bNTSC = true; Region = USA_DIR; break; case DiscIO::IVolume::COUNTRY_TAIWAN: case DiscIO::IVolume::COUNTRY_KOREA: // TODO: Should these have their own Region Dir? case DiscIO::IVolume::COUNTRY_JAPAN: bNTSC = true; Region = JAP_DIR; break; case DiscIO::IVolume::COUNTRY_EUROPE: case DiscIO::IVolume::COUNTRY_FRANCE: case DiscIO::IVolume::COUNTRY_ITALY: case DiscIO::IVolume::COUNTRY_RUSSIA: bNTSC = false; Region = EUR_DIR; break; default: if (PanicYesNoT("Your GCM/ISO file seems to be invalid (invalid country)." "\nContinue with PAL region?")) { bNTSC = false; Region = EUR_DIR; break; } else { return false; } } } else if (!strcasecmp(Extension.c_str(), ".elf")) { bWii = CBoot::IsElfWii(m_strFilename); Region = USA_DIR; m_BootType = BOOT_ELF; bNTSC = true; } else if (!strcasecmp(Extension.c_str(), ".dol")) { CDolLoader dolfile(m_strFilename); bWii = dolfile.IsWii(); Region = USA_DIR; m_BootType = BOOT_DOL; bNTSC = true; } else if (!strcasecmp(Extension.c_str(), ".dff")) { bWii = true; Region = USA_DIR; bNTSC = true; m_BootType = BOOT_DFF; std::unique_ptr<FifoDataFile> ddfFile(FifoDataFile::Load(m_strFilename, true)); if (ddfFile) { bWii = ddfFile->GetIsWii(); } } else if (DiscIO::CNANDContentManager::Access().GetNANDLoader(m_strFilename).IsValid()) { std::unique_ptr<DiscIO::IVolume> pVolume(DiscIO::CreateVolumeFromFilename(m_strFilename)); const DiscIO::INANDContentLoader& ContentLoader = DiscIO::CNANDContentManager::Access().GetNANDLoader(m_strFilename); if (ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex()) == nullptr) { //WAD is valid yet cannot be booted. Install instead. u64 installed = DiscIO::CNANDContentManager::Access().Install_WiiWAD(m_strFilename); if (installed) SuccessAlertT("The WAD has been installed successfully"); return false; //do not boot } switch (ContentLoader.GetCountry()) { case DiscIO::IVolume::COUNTRY_USA: bNTSC = true; Region = USA_DIR; break; case DiscIO::IVolume::COUNTRY_TAIWAN: case DiscIO::IVolume::COUNTRY_KOREA: // TODO: Should these have their own Region Dir? case DiscIO::IVolume::COUNTRY_JAPAN: bNTSC = true; Region = JAP_DIR; break; case DiscIO::IVolume::COUNTRY_EUROPE: case DiscIO::IVolume::COUNTRY_FRANCE: case DiscIO::IVolume::COUNTRY_ITALY: case DiscIO::IVolume::COUNTRY_RUSSIA: bNTSC = false; Region = EUR_DIR; break; default: bNTSC = false; Region = EUR_DIR; break; } bWii = true; m_BootType = BOOT_WII_NAND; if (pVolume) { m_strName = pVolume->GetName(); m_strUniqueID = pVolume->GetUniqueID(); } else { // null pVolume means that we are loading from nand folder (Most Likely Wii Menu) // if this is the second boot we would be using the Name and id of the last title m_strName.clear(); m_strUniqueID.clear(); } // Use the TitleIDhex for name and/or unique ID if launching from nand folder // or if it is not ascii characters (specifically sysmenu could potentially apply to other things) std::string titleidstr = StringFromFormat("%016" PRIx64, ContentLoader.GetTitleID()); if (m_strName.empty()) { m_strName = titleidstr; } if (m_strUniqueID.empty()) { m_strUniqueID = titleidstr; } } else { PanicAlertT("Could not recognize ISO file %s", m_strFilename.c_str()); return false; } } break; case BOOT_BS2_USA: Region = USA_DIR; m_strFilename.clear(); bNTSC = true; break; case BOOT_BS2_JAP: Region = JAP_DIR; m_strFilename.clear(); bNTSC = true; break; case BOOT_BS2_EUR: Region = EUR_DIR; m_strFilename.clear(); bNTSC = false; break; } // Setup paths CheckMemcardPath(SConfig::GetInstance().m_strMemoryCardA, Region, true); CheckMemcardPath(SConfig::GetInstance().m_strMemoryCardB, Region, false); m_strSRAM = File::GetUserPath(F_GCSRAM_IDX); if (!bWii) { if (!bHLE_BS2) { m_strBootROM = File::GetUserPath(D_GCUSER_IDX) + DIR_SEP + Region + DIR_SEP GC_IPL; if (!File::Exists(m_strBootROM)) m_strBootROM = File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + Region + DIR_SEP GC_IPL; if (!File::Exists(m_strBootROM)) { WARN_LOG(BOOT, "Bootrom file %s not found - using HLE.", m_strBootROM.c_str()); bHLE_BS2 = true; } } } else if (bWii && !bHLE_BS2) { WARN_LOG(BOOT, "GC bootrom file will not be loaded for Wii mode."); bHLE_BS2 = true; } return true; }
bool SConfig::AutoSetup(EBootBS2 _BootBS2) { std::string set_region_dir(EUR_DIR); switch (_BootBS2) { case BOOT_DEFAULT: { bool bootDrive = cdio_is_cdrom(m_strFilename); // Check if the file exist, we may have gotten it from a --elf command line // that gave an incorrect file name if (!bootDrive && !File::Exists(m_strFilename)) { PanicAlertT("The specified file \"%s\" does not exist", m_strFilename.c_str()); return false; } std::string Extension; SplitPath(m_strFilename, nullptr, nullptr, &Extension); if (!strcasecmp(Extension.c_str(), ".gcm") || !strcasecmp(Extension.c_str(), ".iso") || !strcasecmp(Extension.c_str(), ".wbfs") || !strcasecmp(Extension.c_str(), ".ciso") || !strcasecmp(Extension.c_str(), ".gcz") || bootDrive) { m_BootType = BOOT_ISO; std::unique_ptr<DiscIO::IVolume> pVolume(DiscIO::CreateVolumeFromFilename(m_strFilename)); if (pVolume == nullptr) { if (bootDrive) PanicAlertT("Could not read \"%s\". " "There is no disc in the drive, or it is not a GC/Wii backup. " "Please note that original GameCube and Wii discs cannot be read " "by most PC DVD drives.", m_strFilename.c_str()); else PanicAlertT("\"%s\" is an invalid GCM/ISO file, or is not a GC/Wii ISO.", m_strFilename.c_str()); return false; } m_strName = pVolume->GetInternalName(); m_strUniqueID = pVolume->GetUniqueID(); m_revision = pVolume->GetRevision(); // Check if we have a Wii disc bWii = pVolume->GetVolumeType() == DiscIO::IVolume::WII_DISC; const char* retrieved_region_dir = GetRegionOfCountry(pVolume->GetCountry()); if (!retrieved_region_dir) { if (!PanicYesNoT("Your GCM/ISO file seems to be invalid (invalid country)." "\nContinue with PAL region?")) return false; retrieved_region_dir = EUR_DIR; } set_region_dir = retrieved_region_dir; bNTSC = set_region_dir == USA_DIR || set_region_dir == JAP_DIR; } else if (!strcasecmp(Extension.c_str(), ".elf")) { bWii = CBoot::IsElfWii(m_strFilename); // TODO: Right now GC homebrew boots in NTSC and Wii homebrew in PAL. // This is intentional so that Wii homebrew can boot in both 50Hz and 60Hz, without forcing all GC homebrew to 50Hz. // In the future, it probably makes sense to add a Region setting for homebrew somewhere in the emulator config. bNTSC = bWii ? false : true; set_region_dir = bNTSC ? USA_DIR : EUR_DIR; m_BootType = BOOT_ELF; } else if (!strcasecmp(Extension.c_str(), ".dol")) { CDolLoader dolfile(m_strFilename); bWii = dolfile.IsWii(); // TODO: See the ELF code above. bNTSC = bWii ? false : true; set_region_dir = bNTSC ? USA_DIR : EUR_DIR; m_BootType = BOOT_DOL; } else if (!strcasecmp(Extension.c_str(), ".dff")) { bWii = true; set_region_dir = USA_DIR; bNTSC = true; m_BootType = BOOT_DFF; std::unique_ptr<FifoDataFile> ddfFile(FifoDataFile::Load(m_strFilename, true)); if (ddfFile) { bWii = ddfFile->GetIsWii(); } } else if (DiscIO::CNANDContentManager::Access().GetNANDLoader(m_strFilename).IsValid()) { std::unique_ptr<DiscIO::IVolume> pVolume(DiscIO::CreateVolumeFromFilename(m_strFilename)); const DiscIO::CNANDContentLoader& ContentLoader = DiscIO::CNANDContentManager::Access().GetNANDLoader(m_strFilename); if (ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex()) == nullptr) { //WAD is valid yet cannot be booted. Install instead. u64 installed = DiscIO::CNANDContentManager::Access().Install_WiiWAD(m_strFilename); if (installed) SuccessAlertT("The WAD has been installed successfully"); return false; //do not boot } const char* retrieved_region_dir = GetRegionOfCountry(ContentLoader.GetCountry()); set_region_dir = retrieved_region_dir ? retrieved_region_dir : EUR_DIR; bNTSC = set_region_dir == USA_DIR || set_region_dir == JAP_DIR; bWii = true; m_BootType = BOOT_WII_NAND; if (pVolume) { m_strName = pVolume->GetInternalName(); m_strUniqueID = pVolume->GetUniqueID(); } else { // null pVolume means that we are loading from nand folder (Most Likely Wii Menu) // if this is the second boot we would be using the Name and id of the last title m_strName.clear(); m_strUniqueID.clear(); } // Use the TitleIDhex for name and/or unique ID if launching from nand folder // or if it is not ascii characters (specifically sysmenu could potentially apply to other things) std::string titleidstr = StringFromFormat("%016" PRIx64, ContentLoader.GetTitleID()); if (m_strName.empty()) { m_strName = titleidstr; } if (m_strUniqueID.empty()) { m_strUniqueID = titleidstr; } } else { PanicAlertT("Could not recognize ISO file %s", m_strFilename.c_str()); return false; } } break; case BOOT_BS2_USA: set_region_dir = USA_DIR; m_strFilename.clear(); bNTSC = true; break; case BOOT_BS2_JAP: set_region_dir = JAP_DIR; m_strFilename.clear(); bNTSC = true; break; case BOOT_BS2_EUR: set_region_dir = EUR_DIR; m_strFilename.clear(); bNTSC = false; break; } // Setup paths CheckMemcardPath(SConfig::GetInstance().m_strMemoryCardA, set_region_dir, true); CheckMemcardPath(SConfig::GetInstance().m_strMemoryCardB, set_region_dir, false); m_strSRAM = File::GetUserPath(F_GCSRAM_IDX); if (!bWii) { if (!bHLE_BS2) { m_strBootROM = File::GetUserPath(D_GCUSER_IDX) + DIR_SEP + set_region_dir + DIR_SEP GC_IPL; if (!File::Exists(m_strBootROM)) m_strBootROM = File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + set_region_dir + DIR_SEP GC_IPL; if (!File::Exists(m_strBootROM)) { WARN_LOG(BOOT, "Bootrom file %s not found - using HLE.", m_strBootROM.c_str()); bHLE_BS2 = true; } } } else if (bWii && !bHLE_BS2) { WARN_LOG(BOOT, "GC bootrom file will not be loaded for Wii mode."); bHLE_BS2 = true; } return true; }
void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) { int index_A = m_MemcardList[SLOT_A]->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); int index_B = m_MemcardList[SLOT_B]->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); int slot = SLOT_B; int slot2 = SLOT_A; std::string fileName2(""); if (index_A != wxNOT_FOUND && page[SLOT_A]) index_A += itemsPerPage * page[SLOT_A]; if (index_B != wxNOT_FOUND && page[SLOT_B]) index_B += itemsPerPage * page[SLOT_B]; int index = index_B; switch (event.GetId()) { case ID_COPYFROM_B: slot = SLOT_A; slot2 = SLOT_B; case ID_COPYFROM_A: index = slot2 ? index_B : index_A; index = memoryCard[slot2]->GetFileIndex(index); if ((index != wxNOT_FOUND)) { CopyDeleteSwitch(memoryCard[slot]->CopyFrom(*memoryCard[slot2], index), slot); } break; case ID_FIXCHECKSUM_A: slot = SLOT_A; case ID_FIXCHECKSUM_B: if (memoryCard[slot]->FixChecksums() && memoryCard[slot]->Save()) { SuccessAlertT("The checksum was successfully fixed"); } else { PanicAlertT(E_SAVEFAILED); } break; case ID_CONVERTTOGCI: fileName2 = "convert"; case ID_SAVEIMPORT_A: slot = SLOT_A; case ID_SAVEIMPORT_B: { wxString fileName = wxFileSelector( _("Select a save file to import"), (strcmp(DefaultIOPath.c_str(), "/Users/GC") == 0) ? StrToWxStr("") : StrToWxStr(DefaultIOPath), wxEmptyString, wxEmptyString, _("GameCube Savegame files(*.gci;*.gcs;*.sav)") + wxString("|*.gci;*.gcs;*.sav|") + _("Native GCI files(*.gci)") + wxString("|*.gci|") + _("MadCatz Gameshark files(*.gcs)") + wxString("|*.gcs|") + _("Datel MaxDrive/Pro files(*.sav)") + wxString("|*.sav"), wxFD_OPEN | wxFD_FILE_MUST_EXIST, this); if (!fileName.empty() && !fileName2.empty()) { wxString temp2 = wxFileSelector(_("Save GCI as..."), wxEmptyString, wxEmptyString, ".gci", _("GCI File(*.gci)") + wxString("|*.gci"), wxFD_OVERWRITE_PROMPT|wxFD_SAVE, this); if (temp2.empty()) break; fileName2 = WxStrToStr(temp2); } if (fileName.length() > 0) { CopyDeleteSwitch(memoryCard[slot]->ImportGci(WxStrToStr(fileName), fileName2), slot); } } break; case ID_SAVEEXPORT_A: slot=SLOT_A; index = index_A; case ID_SAVEEXPORT_B: index = memoryCard[slot]->GetFileIndex(index); if (index != wxNOT_FOUND) { std::string gciFilename; if (!memoryCard[slot]->GCI_FileName(index, gciFilename)) { PanicAlertT("Invalid index"); return; } wxString fileName = wxFileSelector( _("Export save as..."), StrToWxStr(DefaultIOPath), StrToWxStr(gciFilename), ".gci", _("Native GCI files(*.gci)") + wxString("|*.gci|") + _("MadCatz Gameshark files(*.gcs)") + wxString("|*.gcs|") + _("Datel MaxDrive/Pro files(*.sav)") + wxString("|*.sav"), wxFD_OVERWRITE_PROMPT|wxFD_SAVE, this); if (fileName.length() > 0) { if (!CopyDeleteSwitch(memoryCard[slot]->ExportGci(index, WxStrToStr(fileName), ""), -1)) { File::Delete(WxStrToStr(fileName)); } } } break; case ID_EXPORTALL_A: slot=SLOT_A; case ID_EXPORTALL_B: { std::string path1, path2, mpath; mpath = WxStrToStr(m_MemcardPath[slot]->GetPath()); SplitPath(mpath, &path1, &path2, nullptr); path1 += path2; File::CreateDir(path1); if (PanicYesNoT("Warning: This will overwrite any existing saves that are in the folder:\n" "%s\nand have the same name as a file on your memcard\nContinue?", path1.c_str())) for (int i = 0; i < DIRLEN; i++) { CopyDeleteSwitch(memoryCard[slot]->ExportGci(i, "", path1), -1); } break; } case ID_DELETE_A: slot = SLOT_A; index = index_A; case ID_DELETE_B: index = memoryCard[slot]->GetFileIndex(index); if (index != wxNOT_FOUND) { CopyDeleteSwitch(memoryCard[slot]->RemoveFile(index), slot); } break; } }
bool CMemcardManager::CopyDeleteSwitch(u32 error, int slot) { switch (error) { case GCS: SuccessAlertT("File converted to .gci"); break; case SUCCESS: if (slot != -1) { memoryCard[slot]->FixChecksums(); if (!memoryCard[slot]->Save()) PanicAlertT(E_SAVEFAILED); page[slot] = FIRSTPAGE; ReloadMemcard(WxStrToStr(m_MemcardPath[slot]->GetPath()), slot); } break; case NOMEMCARD: PanicAlertT("File is not recognized as a memcard"); break; case OPENFAIL: PanicAlertT("File could not be opened\nor does not have a valid extension"); break; case OUTOFBLOCKS: if (slot == -1) { PanicAlertT(E_UNK); break; } PanicAlertT("Only %d blocks available", memoryCard[slot]->GetFreeBlocks()); break; case OUTOFDIRENTRIES: PanicAlertT("No free dir index entries"); break; case LENGTHFAIL: PanicAlertT("Imported file has invalid length"); break; case INVALIDFILESIZE: PanicAlertT("The save you are trying to copy has an invalid file size"); break; case TITLEPRESENT: PanicAlertT("Memcard already has a save for this title"); break; case SAVFAIL: PanicAlertT("Imported file has sav extension\nbut does not have a correct header"); break; case GCSFAIL: PanicAlertT("Imported file has gsc extension\nbut does not have a correct header"); break; case FAIL: if (slot == -1) { PanicAlertT("Export Failed"); return false; } PanicAlertT("Invalid bat.map or dir entry"); break; case WRITEFAIL: PanicAlertT(E_SAVEFAILED); break; case DELETE_FAIL: PanicAlertT("Order of files in the File Directory do not match the block order\n" "Right click and export all of the saves,\nand import the saves to a new memcard\n"); break; default: PanicAlertT(E_UNK); break; } SetFocus(); return true; }
void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) { int index_A = m_MemcardList[SLOT_A]->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); int index_B = m_MemcardList[SLOT_B]->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); int slot = SLOT_B; int slot2 = SLOT_A; int index = index_B; std::string fileName2(""); if (index_A != wxNOT_FOUND && page[SLOT_A]) index_A += itemsPerPage * page[SLOT_A]; if (index_B != wxNOT_FOUND && page[SLOT_B]) index_B += itemsPerPage * page[SLOT_B]; switch (event.GetId()) { case ID_COPYFROM_B: slot = SLOT_A; slot2 = SLOT_B; case ID_COPYFROM_A: index = slot2 ? index_B : index_A; if ((index != wxNOT_FOUND)) { CopyDeleteSwitch(memoryCard[slot]->CopyFrom(*memoryCard[slot2], index), slot); } break; case ID_FIXCHECKSUM_A: slot = SLOT_A; case ID_FIXCHECKSUM_B: if (memoryCard[slot]->FixChecksums() && memoryCard[slot]->Save()) { SuccessAlertT("The checksum was successfully fixed"); } else PanicAlert(E_SAVEFAILED); break; case ID_CONVERTTOGCI: fileName2 = "convert"; case ID_SAVEIMPORT_A: slot = SLOT_A; case ID_SAVEIMPORT_B: { wxString fileName = wxFileSelector( _("Select a save file to import"), (strcmp(DefaultIOPath.c_str(), "/Users/GC") == 0) ? wxString::FromAscii("") : wxString::From8BitData(DefaultIOPath.c_str()), wxEmptyString, wxEmptyString, _("Native GCI files(*.gci)") + wxString(wxT("|*.gci|")) + _("MadCatz Gameshark files(*.gcs)") + wxString(wxT("|*.gcs|")) + _("Datel MaxDrive/Pro files(*.sav)") + wxString(wxT("|*.sav")), wxFD_OPEN | wxFD_FILE_MUST_EXIST); if (!fileName.empty() && !fileName2.empty()) { wxString temp2 = wxFileSelector(_("Save GCI as..."), wxEmptyString, wxEmptyString, wxT(".gci"), _("GCI File(*.gci)") + wxString(_T("|*.gci")), wxFD_OVERWRITE_PROMPT|wxFD_SAVE); if (temp2.empty()) break; fileName2 = temp2.mb_str(); } if (fileName.length() > 0) { CopyDeleteSwitch(memoryCard[slot]->ImportGci(fileName.mb_str(), fileName2), slot); } } break; case ID_SAVEEXPORT_A: slot=SLOT_A; index = index_A; case ID_SAVEEXPORT_B: if (index != wxNOT_FOUND) { char tempC[10 + DENTRY_STRLEN], tempC2[DENTRY_STRLEN]; memoryCard[slot]->DEntry_GameCode(index,tempC); memoryCard[slot]->DEntry_FileName(index,tempC2); sprintf(tempC, "%s_%s.gci", tempC, tempC2); wxString fileName = wxFileSelector( _("Export save as..."), wxString::From8BitData(DefaultIOPath.c_str()), wxString::From8BitData(tempC), wxT(".gci"), _("Native GCI files(*.gci)") + wxString(wxT("|*.gci|")) + _("MadCatz Gameshark files(*.gcs)") + wxString(wxT("|*.gcs|")) + _("Datel MaxDrive/Pro files(*.sav)") + wxString(wxT("|*.sav")), wxFD_OVERWRITE_PROMPT|wxFD_SAVE); if (fileName.length() > 0) { if (!CopyDeleteSwitch(memoryCard[slot]->ExportGci(index, fileName.mb_str(), NULL), -1)) { File::Delete(std::string(fileName.mb_str())); } } } break; case ID_EXPORTALL_A: slot=SLOT_A; case ID_EXPORTALL_B: { std::string path1, path2, mpath; mpath = m_MemcardPath[slot]->GetPath().mb_str(); SplitPath(mpath, &path1, &path2, NULL); path1 += path2; File::CreateDir(path1); if(PanicYesNoT("Warning: This will overwrite any existing saves that are in the folder:\n" "%s\nand have the same name as a file on your memcard\nContinue?", path1.c_str())) for (int i = 0; i < DIRLEN; i++) { CopyDeleteSwitch(memoryCard[slot]->ExportGci(i, ".", &path1), -1); } break; } case ID_DELETE_A: slot = SLOT_A; index = index_A; case ID_DELETE_B: if (index != wxNOT_FOUND) { CopyDeleteSwitch(memoryCard[slot]->RemoveFile(index), slot); } break; } }
// This one can load both leftover map files on game discs (like Zelda), and mapfiles // produced by SaveSymbolMap below. // bad=true means carefully load map files that might not be from exactly the right version bool PPCSymbolDB::LoadMap(const std::string& filename, bool bad) { File::IOFile f(filename, "r"); if (!f) return false; // four columns are used in American Mensa Academy map files and perhaps other games bool started = false, four_columns = false; int good_count = 0, bad_count = 0; char line[512]; while (fgets(line, 512, f.GetHandle())) { size_t length = strlen(line); if (length < 4) continue; if (length == 34 && strcmp(line, " address Size address offset\n") == 0) { four_columns = true; continue; } char temp[256]; sscanf(line, "%255s", temp); if (strcmp(temp, "UNUSED")==0) continue; if (strcmp(temp, ".text")==0) {started = true; continue;}; if (strcmp(temp, ".init")==0) {started = true; continue;}; if (strcmp(temp, "Starting")==0) continue; if (strcmp(temp, "extab")==0) continue; if (strcmp(temp, ".ctors")==0) break; //uh? if (strcmp(temp, ".dtors")==0) break; if (strcmp(temp, ".rodata")==0) continue; if (strcmp(temp, ".data")==0) continue; if (strcmp(temp, ".sbss")==0) continue; if (strcmp(temp, ".sdata")==0) continue; if (strcmp(temp, ".sdata2")==0) continue; if (strcmp(temp, "address")==0) continue; if (strcmp(temp, "-----------------------")==0) continue; if (strcmp(temp, ".sbss2")==0) break; if (temp[1] == ']') continue; if (!started) continue; u32 address, vaddress, size, offset, unknown; char name[512], container[512]; if (four_columns) { // sometimes there is no unknown number, and sometimes it is because it is an entry of something else if (length > 37 && line[37]==' ') { unknown = 0; sscanf(line, "%08x %08x %08x %08x %511s", &address, &size, &vaddress, &offset, name); char *s = strstr(line, "(entry of "); if (s) { sscanf(s + 10, "%511s", container); char *s2 = (strchr(container, ')')); if (s2 && container[0]!='.') { s2[0] = '\0'; strcat(container, "::"); strcat(container, name); strcpy(name, container); } } } else { sscanf(line, "%08x %08x %08x %08x %i %511s", &address, &size, &vaddress, &offset, &unknown, name); } } // some entries in the table have a function name followed by " (entry of " followed by a container name, followed by ")" // instead of a space followed by a number followed by a space followed by a name else if (length > 27 && line[27] != ' ' && strstr(line, "(entry of ")) { unknown = 0; sscanf(line, "%08x %08x %08x %511s", &address, &size, &vaddress, name); char *s = strstr(line, "(entry of "); if (s) { sscanf(s + 10, "%511s", container); char *s2 = (strchr(container, ')')); if (s2 && container[0] != '.') { s2[0] = '\0'; strcat(container, "::"); strcat(container, name); strcpy(name, container); } } } else { sscanf(line, "%08x %08x %08x %i %511s", &address, &size, &vaddress, &unknown, name); } const char *namepos = strstr(line, name); if (namepos != nullptr) //would be odd if not :P strcpy(name, namepos); name[strlen(name) - 1] = 0; // we want the function names only .... TODO: or do we really? aren't we wasting information here? for (size_t i = 0; i < strlen(name); i++) { if (name[i] == ' ') name[i] = 0x00; if (name[i] == '(') name[i] = 0x00; } // Check if this is a valid entry. if (strcmp(name, ".text") != 0 && strcmp(name, ".init") != 0 && strlen(name) > 0) { vaddress |= 0x80000000; bool good = !bad; if (!good) { // check for BLR before function u32 opcode = PowerPC::HostRead_Instruction(vaddress - 4); if (opcode == 0x4e800020) { // check for BLR at end of function opcode = PowerPC::HostRead_Instruction(vaddress + size - 4); if (opcode == 0x4e800020) good = true; } } if (good) { ++good_count; AddKnownSymbol(vaddress | 0x80000000, size, name); // ST_FUNCTION } else { ++bad_count; } } } Index(); if (bad) SuccessAlertT("Loaded %d good functions, ignored %d bad functions.", good_count, bad_count); return true; }
// This one can load both leftover map files on game discs (like Zelda), and mapfiles // produced by SaveSymbolMap below. // bad=true means carefully load map files that might not be from exactly the right version bool PPCSymbolDB::LoadMap(const std::string& filename, bool bad) { File::IOFile f(filename, "r"); if (!f) return false; // four columns are used in American Mensa Academy map files and perhaps other games bool four_columns = false; int good_count = 0; int bad_count = 0; char line[512]; std::string section_name; while (fgets(line, 512, f.GetHandle())) { size_t length = strlen(line); if (length < 4) continue; if (length == 34 && strcmp(line, " address Size address offset\n") == 0) { four_columns = true; continue; } char temp[256]; sscanf(line, "%255s", temp); if (strcmp(temp, "UNUSED") == 0) continue; // Support CodeWarrior and Dolphin map if (StringEndsWith(line, " section layout\n") || strcmp(temp, ".text") == 0 || strcmp(temp, ".init") == 0) { section_name = temp; continue; } // Skip four columns' header. // // Four columns example: // // .text section layout // Starting Virtual // address Size address // ----------------------- if (strcmp(temp, "Starting") == 0) continue; if (strcmp(temp, "address") == 0) continue; if (strcmp(temp, "-----------------------") == 0) continue; // Skip link map. // // Link map example: // // Link map of __start // 1] __start(func, weak) found in os.a __start.c // 2] __init_registers(func, local) found in os.a __start.c // 3] _stack_addr found as linker generated symbol // ... // 10] EXILock(func, global) found in exi.a EXIBios.c if (StringEndsWith(temp, "]")) continue; // TODO - Handle/Write a parser for: // - Memory map // - Link map // - Linker generated symbols if (section_name.empty()) continue; u32 address, vaddress, size, offset, alignment; char name[512], container[512]; if (four_columns) { // sometimes there is no alignment value, and sometimes it is because it is an entry of // something else if (length > 37 && line[37] == ' ') { alignment = 0; sscanf(line, "%08x %08x %08x %08x %511s", &address, &size, &vaddress, &offset, name); char* s = strstr(line, "(entry of "); if (s) { sscanf(s + 10, "%511s", container); char* s2 = (strchr(container, ')')); if (s2 && container[0] != '.') { s2[0] = '\0'; strcat(container, "::"); strcat(container, name); strcpy(name, container); } } } else { sscanf(line, "%08x %08x %08x %08x %i %511s", &address, &size, &vaddress, &offset, &alignment, name); } } // some entries in the table have a function name followed by " (entry of " followed by a // container name, followed by ")" // instead of a space followed by a number followed by a space followed by a name else if (length > 27 && line[27] != ' ' && strstr(line, "(entry of ")) { alignment = 0; sscanf(line, "%08x %08x %08x %511s", &address, &size, &vaddress, name); char* s = strstr(line, "(entry of "); if (s) { sscanf(s + 10, "%511s", container); char* s2 = (strchr(container, ')')); if (s2 && container[0] != '.') { s2[0] = '\0'; strcat(container, "::"); strcat(container, name); strcpy(name, container); } } } else { sscanf(line, "%08x %08x %08x %i %511s", &address, &size, &vaddress, &alignment, name); } const char* namepos = strstr(line, name); if (namepos != nullptr) // would be odd if not :P strcpy(name, namepos); name[strlen(name) - 1] = 0; if (name[strlen(name) - 1] == '\r') name[strlen(name) - 1] = 0; // Check if this is a valid entry. if (strlen(name) > 0) { // Can't compute the checksum if not in RAM bool good = !bad && PowerPC::HostIsInstructionRAMAddress(vaddress) && PowerPC::HostIsInstructionRAMAddress(vaddress + size - 4); if (!good) { // check for BLR before function PowerPC::TryReadInstResult read_result = PowerPC::TryReadInstruction(vaddress - 4); if (read_result.valid && read_result.hex == 0x4e800020) { // check for BLR at end of function read_result = PowerPC::TryReadInstruction(vaddress + size - 4); good = read_result.valid && read_result.hex == 0x4e800020; } } if (good) { ++good_count; if (section_name == ".text" || section_name == ".init") AddKnownSymbol(vaddress, size, name, Symbol::Type::Function); else AddKnownSymbol(vaddress, size, name, Symbol::Type::Data); } else { ++bad_count; } } } Index(); if (bad) SuccessAlertT("Loaded %d good functions, ignored %d bad functions.", good_count, bad_count); return true; }