/// <summary> /// Loads or creates a new instance of the user-defined program information table. /// </summary> /// <param name="localFilePath">Absolute path to a file storing the user-specified program information.</param> /// <returns>If the file path is valid, the returned table contains the user's locally defined program information. Otherwise, a new, /// empty table is returned.</returns> public static IProgramInformationTable Initialize(string localFilePath) { UserSpecifiedProgramInformationTable table = null; try { using (var fileStream = StreamUtilities.OpenFileStream(localFilePath)) { if (fileStream != null) { var serializer = new System.Xml.Serialization.XmlSerializer(typeof(UserSpecifiedProgramInformationTable)); table = serializer.Deserialize(fileStream) as UserSpecifiedProgramInformationTable; } } } catch (Exception) { // TODO Silently fail to load user-defined ROMs for now. Eventually need to report back to user once this is supported. table = null; } if (table == null) { // Return an empty instance, which can be harmlessly merged into the master in-memory database. table = new UserSpecifiedProgramInformationTable(); } return(table); }
protected override int GetMemo(string filePath, object data) { CalledGetMemo = true; var stream = StreamUtilities.OpenFileStream(filePath, StorageAccess); var memoValue = ComputeMemoValue(stream); return(memoValue); }
public void FileMemo_AddValidMemoThenAddInvalidMemorForSamePath_MemoIsRemoved() { var testFileName = "~/add-valid-then-add-invalid-dat"; int memo = 42; // just use a bogus memo var memos = new TestFileMemo(); using (StreamUtilities.OpenFileStream(testFileName, memos.Storage)) { Assert.True(memos.AddMemo(testFileName, memo)); Assert.False(memos.AddMemo(testFileName, TestFileMemo.InitialMemoValue)); } }
public void StreamUtilitiesWithTestStorage_CallOpenFileStream_ReturnsValidStream() { var storage = new TestStorageAccess(); var testPath = @"~/open_create_path.dat"; using (var stream = StreamUtilities.OpenFileStream(testPath, storage)) { Assert.True(StreamUtilities.FileExists(testPath, storage)); Assert.NotNull(stream); } Assert.False(StreamUtilities.FileExists(testPath, storage)); }
public void FileMemo_AddMemoOfFileThatIsThenDeletedAndAddedAgain_MemoAddedThenRemoved() { var testFileName = "~/delete-this-test-file.dat"; int memo = 42; // just use a bogus memo var memos = new TestFileMemo(); using (StreamUtilities.OpenFileStream(testFileName, memos.Storage)) { Assert.True(memos.AddMemo(testFileName, memo)); } Assert.False(memos.AddMemo(testFileName, memo)); }
/// <summary> /// Given an absolute path to a ROM file, attempt to determine the format of the ROM. /// </summary> /// <param name="filePath">Absolute path to the potential ROM file.</param> /// <returns>The format of the file. If it does not appear to be a ROM, then <c>RomFormat.None</c> is returned.</returns> internal static RomFormat CheckFormat(string filePath) { var format = CheckMemo(filePath); if (format == RomFormat.None) { using (var file = StreamUtilities.OpenFileStream(filePath)) { format = CheckFormat(file); } } return(format); }
public void Crc32_OfFileWithAlternateFirstByte_IsCorrect() { // We use a privately defined type for the storage access to check initialize and remove, which will // hopefully guarantee that we use the expected storage during this test. var storageAcces = new Crc32TestStorageAccess(); var testFileName = "~/Crc32_OfFileWithAlternateFirstByte_IsCorrect.dat"; StreamUtilities.Initialize(storageAcces); using (var fileStream = StreamUtilities.OpenFileStream(testFileName)) { var testData = new byte[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; fileStream.Write(testData, 0, testData.Length); var crc32 = Crc32.OfFile(testFileName, replaceFirstByte: true, alternateFirstByte: 0x42); Assert.Equal(0x066F5C62u, crc32); } }
public void Crc24_OfFile_IsCorrect() { // We use a privately defined type for the storage access to check initialize and remove, which will // hopefully guarantee that we use the expected storage during this test. var storageAcces = new Crc24TestStorageAccess(); StreamUtilities.Initialize(storageAcces); var testFileName = "~/Crc24_OfFile_IsCorrect.dat"; using (var fileStream = StreamUtilities.OpenFileStream(testFileName)) { var testData = new byte[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; fileStream.Write(testData, 0, testData.Length); var crc24 = Crc24.OfFile(testFileName); Assert.Equal(0x004F40DAu, crc24); } }
public void Crc32_OfFileWithIgnoreRange_IsCorrect() { // We use a privately defined type for the storage access to check initialize and remove, which will // hopefully guarantee that we use the expected storage during this test. var storageAcces = new Crc32TestStorageAccess(); StreamUtilities.Initialize(storageAcces); var testFileName = "~/Crc32_OfFileWithIgnoreRange_IsCorrect.dat"; using (var fileStream = StreamUtilities.OpenFileStream(testFileName)) { var testData = new byte[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; fileStream.Write(testData, 0, testData.Length); var ignoreRanges = new[] { new Range <int>(1, 2) }; var crc32 = Crc32.OfFile(testFileName, ignoreRanges); Assert.Equal(0xB4DA8CCAu, crc32); } }
/// <summary> /// Locates the first data block of the requested type in the ROM. /// </summary> /// <typeparam name="T">The type of LUIGI block to locate.</typeparam> /// <returns>The data block, or <c>null</c> if no block of the requested type is in the ROM.</returns> internal T LocateDataBlock <T>() where T : LuigiDataBlock { var dataBlock = default(T); if (StreamUtilities.FileExists(RomPath)) { using (var file = StreamUtilities.OpenFileStream(RomPath)) { if (file != null) { if (file.Length > 0) { var desiredBlockType = LuigiDataBlock.GetBlockType <T>(); var luigiHeader = LuigiFileHeader.Inflate(file); var bytesRead = luigiHeader.DeserializeByteCount; // Start looking for desired block immediately after header. var block = LuigiDataBlock.Inflate(file); bytesRead += block.DeserializeByteCount; if (StopIfScrambleKeyBlockFound(desiredBlockType, block.Type)) { // Stop looking. If we hit the scramble key, there's nothing more to be looked at. bytesRead = (int)file.Length; } while ((bytesRead < file.Length) && (block.Type != desiredBlockType) && (block.Type != LuigiDataBlockType.EndOfFile)) { block = LuigiDataBlock.Inflate(file); bytesRead += block.DeserializeByteCount; if (StopIfScrambleKeyBlockFound(desiredBlockType, block.Type)) { break; } } if (block.Type == desiredBlockType) { dataBlock = block as T; } } } } } return(dataBlock); }
public void StreamUtilitiesWithTestStorage_CallLastWriteTimeUtcAfterWritingToStream_ReturnsReasonableLastWriteTime() { var storage = new TestStorageAccess(); var testPath = @"~/test_file_to_write.dat"; using (var stream = StreamUtilities.OpenFileStream(testPath, storage)) { var beforeWrite = DateTime.UtcNow; int numBytesToWrite = 128; for (byte i = 0; i < numBytesToWrite; ++i) { stream.WriteByte(i); } Assert.Equal(numBytesToWrite, StreamUtilities.FileSize(testPath, storage)); var afterWrite = DateTime.UtcNow; var lastWrite = StreamUtilities.LastFileWriteTimeUtc(testPath, storage); Assert.True(lastWrite >= beforeWrite); Assert.True(lastWrite <= afterWrite); } }
/// <summary> /// Given an absolute path to a ROM file, attempt to determine the format of the ROM. /// </summary> /// <param name="filePath">Absolute path to the potential ROM file.</param> /// <returns>The format of the file. If it does not appear to be a ROM, then <c>RomFormat.None</c> is returned.</returns> internal static RomFormat CheckFormat(string filePath) { var format = CheckMemo(filePath); if (format == RomFormat.None) { using (System.IO.Stream file = StreamUtilities.OpenFileStream(filePath)) { var fileSizeCheck = file != null; if (fileSizeCheck) { var allowOddRomFileSize = !ProgramFileKind.Rom.HasCustomRomExtension(filePath); fileSizeCheck = IsValidFileSize(file, allowOddRomFileSize); } if (fileSizeCheck) { format = RomFormat.Bin; } } } return(format); }
/// <summary> /// Checks the format of the ROM at the given absolute path. /// </summary> /// <param name="filePath">Absolute path to a ROM file.</param> /// <returns>The format of the ROM.</returns> internal static RomFormat CheckFormat(string filePath) { var format = CheckMemo(filePath); if (format == RomFormat.None) { using (var file = StreamUtilities.OpenFileStream(filePath)) { if (file != null) { if (file.Length > 0) { if (LuigiFileHeader.GetHeader(filePath) != null) { format = RomFormat.Luigi; AddMemo(filePath, format); } } } } } return(format); }
/// <inheritdoc /> protected override LuigiFileHeader GetMemo(string filePath, object data) { LuigiFileHeader luigiHeader = null; try { using (var file = StreamUtilities.OpenFileStream(filePath)) { var reader = new INTV.Core.Utility.BinaryReader(file); byte[] header = reader.ReadBytes(MagicKey.Length); if (header.SequenceEqual(MagicKey)) { file.Seek(0, System.IO.SeekOrigin.Begin); luigiHeader = LuigiFileHeader.Inflate(file); } } } catch (Exception) { // Just in case the header looks OK, but turns out to be bad. } return(luigiHeader); }
/// <summary> /// Examines the given data stream and attempts to determine if it is in .bin format. /// </summary> /// <param name="filePath">The path to the ROM file.</param> /// <param name="configFilePath">The path to the config file.</param> /// <returns>A valid BinFormatRom if the file appears to be a valid .bin (or similar) file, otherwise <c>null</c>.</returns> /// <remarks>Apparently, there may be odd-sized files floating around out there, in which case this will fail.</remarks> internal static new BinFormatRom Create(string filePath, string configFilePath) { BinFormatRom bin = null; var format = CheckFormat(filePath); if (format == RomFormat.Bin) { using (System.IO.Stream configFile = (configFilePath == null) ? null : StreamUtilities.OpenFileStream(configFilePath)) { // any valid .bin file will be even sized -- except for some available through the Digital Press. For some reason, these all seem to be a multiple of // 8KB + 1 byte in size. So allow those through, too. var configFileCheck = ((configFile != null) && (configFile.Length > 0)) || configFile == null; if (configFileCheck) { bin = new BinFormatRom() { Format = RomFormat.Bin, IsValid = true, RomPath = filePath, ConfigPath = configFilePath }; } } } return(bin); }