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); } } }
bool SysConf::LoadFromFile(const char *filename) { // Basic check if (!File::Exists(filename)) { File::CreateFullPath(filename); GenerateSysConf(); return true; } u64 size = File::GetSize(filename); if (size != SYSCONF_SIZE) { if (AskYesNoT("Your SYSCONF file is the wrong size.\nIt should be 0x%04x (but is 0x%04" PRIx64 ")\nDo you want to generate a new one?", SYSCONF_SIZE, size)) { GenerateSysConf(); return true; } else return false; } File::IOFile f(filename, "rb"); if (f.IsOpen()) { if (LoadFromFileInternal(f.ReleaseHandle())) { m_Filename = filename; return true; } } return false; }
static std::string GetDumpPath(const std::string& format) { if (!g_Config.sDumpPath.empty()) return g_Config.sDumpPath; const std::string dump_path = File::GetUserPath(D_DUMPFRAMES_IDX) + "framedump" + std::to_string(s_file_index) + "." + format; // Ask to delete file if (File::Exists(dump_path)) { if (SConfig::GetInstance().m_DumpFramesSilent || AskYesNoT("Delete the existing file '%s'?", dump_path.c_str())) { File::Delete(dump_path); } else { // Stop and cancel dumping the video return ""; } } return dump_path; }
// Returns false if the hash fails and the user hits "Yes" static bool VerifyRoms() { struct DspRomHashes { u32 hash_irom; // dsp_rom.bin u32 hash_drom; // dsp_coef.bin }; static const std::array<DspRomHashes, 4> known_roms = { {// Official Nintendo ROM {0x66f334fe, 0xf3b93527}, // LM1234 replacement ROM (Zelda UCode only) {0x9c8f593c, 0x10000001}, // delroth's improvement on LM1234 replacement ROM (Zelda and AX only, // IPL/Card/GBA still broken) {0xd9907f71, 0xb019c2fb}, // above with improved resampling coefficients {0xd9907f71, 0xdb6880c1}}}; u32 hash_irom = HashAdler32((u8*)g_dsp.irom, DSP_IROM_BYTE_SIZE); u32 hash_drom = HashAdler32((u8*)g_dsp.coef, DSP_COEF_BYTE_SIZE); int rom_idx = -1; for (size_t i = 0; i < known_roms.size(); ++i) { const DspRomHashes& rom = known_roms[i]; if (hash_irom == rom.hash_irom && hash_drom == rom.hash_drom) rom_idx = static_cast<int>(i); } if (rom_idx < 0) { if (AskYesNoT("Your DSP ROMs have incorrect hashes.\n" "Would you like to stop now to fix the problem?\n" "If you select \"No\", audio might be garbled.")) return false; } if (rom_idx == 1) { DSPHost::OSD_AddMessage("You are using an old free DSP ROM made by the Dolphin Team.", 6000); DSPHost::OSD_AddMessage("Only games using the Zelda UCode will work correctly.", 6000); } else if (rom_idx == 2 || rom_idx == 3) { DSPHost::OSD_AddMessage("You are using a free DSP ROM made by the Dolphin Team.", 8000); DSPHost::OSD_AddMessage("All Wii games will work correctly, and most GC games should ", 8000); DSPHost::OSD_AddMessage("also work fine, but the GBA/IPL/CARD UCodes will not work.\n", 8000); } return true; }
void CWiiSaveCrypted::ReadHDR() { File::IOFile fpData_bin(encryptedSavePath, "rb"); if (!fpData_bin) { PanicAlertT("Cannot open %s", encryptedSavePath.c_str()); b_valid = false; return; } if (!fpData_bin.ReadBytes(&_encryptedHeader, HEADER_SZ)) { PanicAlertT("Failed to read header"); b_valid = false; return; } fpData_bin.Close(); aes_crypt_cbc(&m_AES_ctx, AES_DECRYPT, HEADER_SZ, SD_IV, (const u8*)&_encryptedHeader, (u8*)&_header); u32 bannerSize = Common::swap32(_header.hdr.BannerSize); if ((bannerSize < FULL_BNR_MIN) || (bannerSize > FULL_BNR_MAX) || (((bannerSize - BNR_SZ) % ICON_SZ) != 0)) { PanicAlertT("Not a Wii save or read failure for file header size %x", bannerSize); b_valid = false; return; } m_TitleID = Common::swap64(_header.hdr.SaveGameTitle); u8 md5_file[16]; u8 md5_calc[16]; memcpy(md5_file, _header.hdr.Md5, 0x10); memcpy(_header.hdr.Md5, MD5_BLANKER, 0x10); md5((u8*)&_header, HEADER_SZ, md5_calc); if (memcmp(md5_file, md5_calc, 0x10)) { PanicAlertT("MD5 mismatch\n %016" PRIx64 "%016" PRIx64 " != %016" PRIx64 "%016" PRIx64, Common::swap64(md5_file),Common::swap64(md5_file+8), Common::swap64(md5_calc), Common::swap64(md5_calc+8)); b_valid= false; } if (!getPaths()) { b_valid = false; return; } std::string BannerFilePath = WiiTitlePath + "banner.bin"; if (!File::Exists(BannerFilePath) || AskYesNoT("%s already exists, overwrite?", BannerFilePath.c_str())) { INFO_LOG(CONSOLE, "Creating file %s", BannerFilePath.c_str()); File::IOFile fpBanner_bin(BannerFilePath, "wb"); fpBanner_bin.WriteBytes(_header.BNR, bannerSize); } }
// Returns false iff the hash fails and the user hits "Yes" static bool VerifyRoms(const char *irom_filename, const char *coef_filename) { struct DspRomHashes { u32 hash_irom; // dsp_rom.bin u32 hash_drom; // dsp_coef.bin } KNOWN_ROMS[] = { // Official Nintendo ROM { 0x66f334fe, 0xf3b93527 }, // LM1234 replacement ROM (Zelda UCode only) { 0x9c8f593c, 0x10000001 }, // delroth's improvement on LM1234 replacement ROM (Zelda and AX only, // IPL/Card/GBA still broken) { 0xd9907f71, 0xb019c2fb } }; u32 hash_irom = HashAdler32((u8*)g_dsp.irom, DSP_IROM_BYTE_SIZE); u32 hash_drom = HashAdler32((u8*)g_dsp.coef, DSP_COEF_BYTE_SIZE); int rom_idx = -1; for (u32 i = 0; i < sizeof (KNOWN_ROMS) / sizeof (KNOWN_ROMS[0]); ++i) { DspRomHashes& rom = KNOWN_ROMS[i]; if (hash_irom == rom.hash_irom && hash_drom == rom.hash_drom) rom_idx = i; } if (rom_idx < 0) { if (AskYesNoT("Your DSP ROMs have incorrect hashes.\n" "Would you like to stop now to fix the problem?\n" "If you select \"No\", audio might be garbled.")) return false; } if (rom_idx == 1) { DSPHost_OSD_AddMessage("You are using an old free DSP ROM made by the Dolphin Team.", 6000); DSPHost_OSD_AddMessage("Only games using the Zelda UCode will work correctly.", 6000); } if (rom_idx == 2) { DSPHost_OSD_AddMessage("You are using a free DSP ROM made by the Dolphin Team.", 8000); DSPHost_OSD_AddMessage("All Wii games will work correctly, and most GC games should ", 8000); DSPHost_OSD_AddMessage("also work fine, but the GBA/IPL/CARD UCodes will not work.\n", 8000); } return true; }
void GamepadPage::DeleteProfile(wxCommandEvent&) { std::string fname; GamepadPage::GetProfilePath(fname); const char* const fnamecstr = fname.c_str(); if (File::Exists(fnamecstr) && AskYesNoT("Are you sure you want to delete \"%s\"?", STR_FROM_WXSTR(profile_cbox->GetValue()).c_str())) { File::Delete(fnamecstr); m_config_dialog->UpdateProfileComboBox(); } }
bool Renderer::StartFrameDumpToImage(const FrameDumpConfig& config) { m_frame_dump_image_counter = 1; if (!SConfig::GetInstance().m_DumpFramesSilent) { // Only check for the presence of the first image to confirm overwriting. // A previous run will always have at least one image, and it's safe to assume that if the user // has allowed the first image to be overwritten, this will apply any remaining images as well. std::string filename = GetFrameDumpNextImageFileName(); if (File::Exists(filename)) { if (!AskYesNoT("Frame dump image(s) '%s' already exists. Overwrite?", filename.c_str())) return false; } } return true; }
bool AVIDump::CreateFile() { AVCodec* codec = nullptr; s_format_context = avformat_alloc_context(); std::stringstream s_file_index_str; s_file_index_str << s_file_index; snprintf(s_format_context->filename, sizeof(s_format_context->filename), "%s", (File::GetUserPath(D_DUMPFRAMES_IDX) + "framedump" + s_file_index_str.str() + ".avi") .c_str()); File::CreateFullPath(s_format_context->filename); // Ask to delete file if (File::Exists(s_format_context->filename)) { if (SConfig::GetInstance().m_DumpFramesSilent || AskYesNoT("Delete the existing file '%s'?", s_format_context->filename)) { File::Delete(s_format_context->filename); } else { // Stop and cancel dumping the video return false; } } if (!(s_format_context->oformat = av_guess_format("avi", nullptr, nullptr)) || !(s_stream = avformat_new_stream(s_format_context, codec))) { return false; } s_stream->codec->codec_id = g_Config.bUseFFV1 ? AV_CODEC_ID_FFV1 : s_format_context->oformat->video_codec; if (!g_Config.bUseFFV1) s_stream->codec->codec_tag = MKTAG('X', 'V', 'I', 'D'); // Force XVID FourCC for better compatibility s_stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; s_stream->codec->bit_rate = 400000; s_stream->codec->width = s_width; s_stream->codec->height = s_height; s_stream->codec->time_base.num = 1; s_stream->codec->time_base.den = VideoInterface::GetTargetRefreshRate(); s_stream->codec->gop_size = 12; s_stream->codec->pix_fmt = g_Config.bUseFFV1 ? AV_PIX_FMT_BGRA : AV_PIX_FMT_YUV420P; if (!(codec = avcodec_find_encoder(s_stream->codec->codec_id)) || (avcodec_open2(s_stream->codec, codec, nullptr) < 0)) { return false; } s_src_frame = av_frame_alloc(); s_scaled_frame = av_frame_alloc(); s_scaled_frame->format = s_stream->codec->pix_fmt; s_scaled_frame->width = s_width; s_scaled_frame->height = s_height; #if LIBAVCODEC_VERSION_MAJOR >= 55 if (av_frame_get_buffer(s_scaled_frame, 1)) return false; #else if (avcodec_default_get_buffer(s_stream->codec, s_scaled_frame)) return false; #endif NOTICE_LOG(VIDEO, "Opening file %s for dumping", s_format_context->filename); if (avio_open(&s_format_context->pb, s_format_context->filename, AVIO_FLAG_WRITE) < 0 || avformat_write_header(s_format_context, nullptr)) { WARN_LOG(VIDEO, "Could not open %s", s_format_context->filename); return false; } OSD::AddMessage(StringFromFormat("Dumping Frames to \"%s\" (%dx%d)", s_format_context->filename, s_width, s_height)); return true; }
bool AVIDump::CreateFile() { m_totalBytes = 0; m_frameCount = 0; std::string movie_file_name = StringFromFormat("%sframedump%d.avi", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), m_fileCount); // Create path File::CreateFullPath(movie_file_name); // Ask to delete file if (File::Exists(movie_file_name)) { if (AskYesNoT("Delete the existing file '%s'?", movie_file_name.c_str())) File::Delete(movie_file_name); } AVIFileInit(); NOTICE_LOG(VIDEO, "Opening AVI file (%s) for dumping", movie_file_name.c_str()); // TODO: Make this work with AVIFileOpenW without it throwing REGDB_E_CLASSNOTREG HRESULT hr = AVIFileOpenA(&m_file, movie_file_name.c_str(), OF_WRITE | OF_CREATE, nullptr); if (FAILED(hr)) { if (hr == AVIERR_BADFORMAT) NOTICE_LOG(VIDEO, "The file couldn't be read, indicating a corrupt file or an unrecognized format."); if (hr == AVIERR_MEMORY) NOTICE_LOG(VIDEO, "The file could not be opened because of insufficient memory."); if (hr == AVIERR_FILEREAD) NOTICE_LOG(VIDEO, "A disk error occurred while reading the file."); if (hr == AVIERR_FILEOPEN) NOTICE_LOG(VIDEO, "A disk error occurred while opening the file."); if (hr == REGDB_E_CLASSNOTREG) NOTICE_LOG(VIDEO, "AVI class not registered"); Stop(); return false; } SetBitmapFormat(); NOTICE_LOG(VIDEO, "Setting video format..."); if (!SetVideoFormat()) { NOTICE_LOG(VIDEO, "Setting video format failed"); Stop(); return false; } if (!m_fileCount) { if (!SetCompressionOptions()) { NOTICE_LOG(VIDEO, "SetCompressionOptions failed"); Stop(); return false; } } if (FAILED(AVIMakeCompressedStream(&m_streamCompressed, m_stream, &m_options, nullptr))) { NOTICE_LOG(VIDEO, "AVIMakeCompressedStream failed"); Stop(); return false; } if (FAILED(AVIStreamSetFormat(m_streamCompressed, 0, &m_bitmap, m_bitmap.biSize))) { NOTICE_LOG(VIDEO, "AVIStreamSetFormat failed"); Stop(); return false; } return true; }
bool WaveFileWriter::Start(const std::string& filename, unsigned int HLESampleRate) { // Ask to delete file if (File::Exists(filename)) { if (SConfig::GetInstance().m_DumpAudioSilent || AskYesNoT("Delete the existing file '%s'?", filename.c_str())) { File::Delete(filename); } else { // Stop and cancel dumping the audio return false; } } // Check if the file is already open if (file) { PanicAlertT("The file %s was already open, the file header will not be written.", filename.c_str()); return false; } file.Open(filename, "wb"); if (!file) { PanicAlertT("The file %s could not be opened for writing. Please check if it's already opened " "by another program.", filename.c_str()); return false; } audio_size = 0; if (basename.empty()) SplitPath(filename, nullptr, &basename, nullptr); current_sample_rate = HLESampleRate; // ----------------- // Write file header // ----------------- Write4("RIFF"); Write(100 * 1000 * 1000); // write big value in case the file gets truncated Write4("WAVE"); Write4("fmt "); Write(16); // size of fmt block Write(0x00020001); // two channels, uncompressed const u32 sample_rate = HLESampleRate; Write(sample_rate); Write(sample_rate * 2 * 2); // two channels, 16bit Write(0x00100004); Write4("data"); Write(100 * 1000 * 1000 - 32); // We are now at offset 44 if (file.Tell() != 44) PanicAlert("Wrong offset: %lld", (long long)file.Tell()); return true; }
bool AVIDump::CreateFile() { AVCodec* codec = nullptr; s_format_context = avformat_alloc_context(); snprintf(s_format_context->filename, sizeof(s_format_context->filename), "%s", (File::GetUserPath(D_DUMPFRAMES_IDX) + "framedump0.avi").c_str()); File::CreateFullPath(s_format_context->filename); // Ask to delete file if (File::Exists(s_format_context->filename)) { if (SConfig::GetInstance().m_DumpFramesSilent || AskYesNoT("Delete the existing file '%s'?", s_format_context->filename)) { File::Delete(s_format_context->filename); } else { // Stop and cancel dumping the video return false; } } if (!(s_format_context->oformat = av_guess_format("avi", nullptr, nullptr)) || !(s_stream = avformat_new_stream(s_format_context, codec))) { return false; } s_stream->codec->codec_id = g_Config.bUseFFV1 ? AV_CODEC_ID_FFV1 : s_format_context->oformat->video_codec; if (!g_Config.bUseFFV1) s_stream->codec->codec_tag = MKTAG('X', 'V', 'I', 'D'); // Force XVID FourCC for better compatibility s_stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; s_stream->codec->bit_rate = 400000; s_stream->codec->width = s_width; s_stream->codec->height = s_height; s_stream->codec->time_base.num = 1; s_stream->codec->time_base.den = VideoInterface::TargetRefreshRate; s_stream->codec->gop_size = 12; s_stream->codec->pix_fmt = g_Config.bUseFFV1 ? AV_PIX_FMT_BGRA : AV_PIX_FMT_YUV420P; if (!(codec = avcodec_find_encoder(s_stream->codec->codec_id)) || (avcodec_open2(s_stream->codec, codec, nullptr) < 0)) { return false; } s_src_frame = av_frame_alloc(); s_scaled_frame = av_frame_alloc(); s_size = avpicture_get_size(s_stream->codec->pix_fmt, s_width, s_height); s_yuv_buffer = new uint8_t[s_size]; avpicture_fill((AVPicture*)s_scaled_frame, s_yuv_buffer, s_stream->codec->pix_fmt, s_width, s_height); NOTICE_LOG(VIDEO, "Opening file %s for dumping", s_format_context->filename); if (avio_open(&s_format_context->pb, s_format_context->filename, AVIO_FLAG_WRITE) < 0) { WARN_LOG(VIDEO, "Could not open %s", s_format_context->filename); return false; } avformat_write_header(s_format_context, nullptr); return true; }
void CWiiSaveCrypted::ImportWiiSaveFiles() { if (!b_valid) return; File::IOFile fpData_bin(pathData_bin, "rb"); if (!fpData_bin) { PanicAlertT("Cannot open %s", pathData_bin); b_valid = false; return; } fpData_bin.Seek(HEADER_SZ + BK_SZ, SEEK_SET); FileHDR _tmpFileHDR; for(u32 i = 0; i < _numberOfFiles; i++) { memset(&_tmpFileHDR, 0, FILE_HDR_SZ); memset(IV, 0, 0x10); _fileSize = 0; if (!fpData_bin.ReadBytes(&_tmpFileHDR, FILE_HDR_SZ)) { PanicAlertT("Failed to write header for file %d", i); b_valid = false; } if (Common::swap32(_tmpFileHDR.magic) != FILE_HDR_MAGIC) { PanicAlertT("Bad File Header"); break; } else { std::string fileName ((char*)_tmpFileHDR.name); for (Common::replace_v::const_iterator iter = replacements.begin(); iter != replacements.end(); ++iter) { for (size_t j = 0; (j = fileName.find(iter->first, j)) != fileName.npos; ++j) fileName.replace(j, 1, iter->second); } std::string fullFilePath = WiiTitlePath + fileName; File::CreateFullPath(fullFilePath); if (_tmpFileHDR.type == 1) { _fileSize = Common::swap32(_tmpFileHDR.size); u32 RoundedFileSize = ROUND_UP(_fileSize, BLOCK_SZ); _encryptedData = new u8[RoundedFileSize]; _data = new u8[RoundedFileSize]; if (!fpData_bin.ReadBytes(_encryptedData, RoundedFileSize)) { PanicAlertT("Failed to read data from file %d", i); b_valid = false; break; } memcpy(IV, _tmpFileHDR.IV, 0x10); AES_cbc_encrypt((const unsigned char *)_encryptedData, _data, RoundedFileSize, &m_AES_KEY, IV, AES_DECRYPT); delete []_encryptedData; if (!File::Exists(fullFilePath) || AskYesNoT("%s already exists, overwrite?", fullFilePath.c_str())) { INFO_LOG(CONSOLE, "Creating file %s", fullFilePath.c_str()); File::IOFile fpRawSaveFile(fullFilePath, "wb"); fpRawSaveFile.WriteBytes(_data, _fileSize); } delete []_data; } } } }
bool AVIDump::CreateFile() { s_total_bytes = 0; s_frame_count = 0; std::string movie_file_name = ""; //Dragonbane: Movie Logic bool lastSide = false; movie_file_name = GetCurrDumpFile(s_file_count, false); if (Movie::cmp_isRunning) { if (Movie::cmp_leftFinished || Movie::cmp_rightFinished) lastSide = true; } if (!lastSide) //Dragonbane: Stay silent if last side is recorded { // Create path File::CreateFullPath(movie_file_name); // Ask to delete file if (File::Exists(movie_file_name)) { if (SConfig::GetInstance().m_DumpFramesSilent || AskYesNoT("Delete the existing file '%s'?", movie_file_name.c_str())) { File::Delete(movie_file_name); } } } AVIFileInit(); NOTICE_LOG(VIDEO, "Opening AVI file (%s) for dumping", movie_file_name.c_str()); // TODO: Make this work with AVIFileOpenW without it throwing REGDB_E_CLASSNOTREG HRESULT hr = AVIFileOpenA(&s_file, movie_file_name.c_str(), OF_WRITE | OF_CREATE, nullptr); if (FAILED(hr)) { if (hr == AVIERR_BADFORMAT) NOTICE_LOG(VIDEO, "The file couldn't be read, indicating a corrupt file or an unrecognized format."); if (hr == AVIERR_MEMORY) NOTICE_LOG(VIDEO, "The file could not be opened because of insufficient memory."); if (hr == AVIERR_FILEREAD) NOTICE_LOG(VIDEO, "A disk error occurred while reading the file."); if (hr == AVIERR_FILEOPEN) NOTICE_LOG(VIDEO, "A disk error occurred while opening the file."); if (hr == REGDB_E_CLASSNOTREG) NOTICE_LOG(VIDEO, "AVI class not registered"); Stop(); return false; } SetBitmapFormat(); NOTICE_LOG(VIDEO, "Setting video format..."); if (!SetVideoFormat()) { NOTICE_LOG(VIDEO, "Setting video format failed"); Stop(); return false; } if (!s_file_count && !lastSide) //Dragonbane: Stay silent and re-use settings if last side is recorded { if (!SetCompressionOptions()) { NOTICE_LOG(VIDEO, "SetCompressionOptions failed"); Stop(); return false; } } if (FAILED(AVIMakeCompressedStream(&s_stream_compressed, s_stream, &s_options, nullptr))) { NOTICE_LOG(VIDEO, "AVIMakeCompressedStream failed"); Stop(); return false; } if (FAILED(AVIStreamSetFormat(s_stream_compressed, 0, &s_bitmap, s_bitmap.biSize))) { NOTICE_LOG(VIDEO, "AVIStreamSetFormat failed"); Stop(); return false; } return true; }