private static IEnumerable <Ddr573DirectoryEntry> DecodeInternal(Ddr573Image image) { if (!image.Modules.Any()) { throw new RhythmCodexException("There must be at least one module in the image."); } if (!image.Modules.ContainsKey(0)) { throw new RhythmCodexException("A module with index 0 must be present in the image."); } var reader = new MemoryReader(image.Modules[0]); Ddr573DirectoryEntry GetDdrFile() { var file = new Ddr573DirectoryEntry { Id = reader.ReadInt32(), Offset = reader.ReadInt16() * 0x800, Module = reader.ReadInt16(), CompressionType = reader.ReadByte(), EncryptionType = reader.ReadByte(), Reserved1 = reader.ReadByte(), Reserved2 = reader.ReadByte(), Length = reader.ReadInt32() }; return(file.Id == 0 ? null : file); } Ddr573DirectoryEntry GetDsFile() { throw new RhythmCodexException("Retrieving Dancing Stage directory entries is not yet supported."); } Func <Ddr573DirectoryEntry> GetDirectoryReader() { reader.Position = 0x24; if (reader.ReadInt32() == PsxIdString) { reader.Position = 0xFE4000; if (reader.ReadInt32() > 0) { reader.Position = 0xFE4000; return(GetDdrFile); } reader.Position = 0x100000; if (reader.ReadInt32() > 0) { reader.Position = 0x100000; return(GetDdrFile); } reader.Position = 0x64F000; if (reader.ReadInt32() > 0) { reader.Position = 0x64F000; return(GetDsFile); } } else { reader.Position = 0x824; if (reader.ReadInt32() == PsxIdString) { reader.Position = 0x100800; if (reader.ReadInt32() > 0) { reader.Position = 0x100800; return(GetDsFile); } } } throw new RhythmCodexException("The directory is not recognized."); } var read = GetDirectoryReader(); while (true) { var entry = read(); if (entry == null) { yield break; } yield return(entry); } }
private IEnumerable <Ddr573File> DecodeInternal(Ddr573Image image, string dbKey) { if (!image.Modules.Any()) { throw new RhythmCodexException("There must be at least one module in the image."); } if (!image.Modules.ContainsKey(0)) { throw new RhythmCodexException("A module with index 0 must be present in the image."); } var readers = image.Modules .ToDictionary(kv => kv.Key, kv => new BinaryReader(new ReadOnlyMemoryStream(kv.Value))); try { foreach (var entry in _ddr573ImageDirectoryDecoder.Decode(image)) { if (!readers.ContainsKey(entry.Module)) { throw new RhythmCodexException($"Module {entry.Module} was requested, but not found."); } var canDecompress = true; var moduleReader = readers[entry.Module]; moduleReader.BaseStream.Position = entry.Offset; Memory <byte> data = moduleReader.ReadBytes(entry.Length); switch (entry.EncryptionType) { case 1: { if (dbKey != null) { data = _ddr573DatabaseDecrypter.Decrypt(data.Span, _ddr573DatabaseDecrypter.ConvertKey(dbKey)); } else { canDecompress = false; } break; } } if (canDecompress) { switch (entry.CompressionType) { case 1: { using (var compressedStream = new ReadOnlyMemoryStream(data)) { try { data = _bemaniLzDecoder.Decode(compressedStream); } catch (Exception) { _logger.Warning($"Entry Id={entry.Id:X8} Module={entry.Module:X4} Offset={entry.Offset:X7} could not be decompressed. It will be extracted as-is."); } } break; } } } yield return(new Ddr573File { Data = data, Id = entry.Id, Module = entry.Module, Offset = entry.Offset, EncryptionType = entry.EncryptionType, Reserved1 = entry.Reserved1, Reserved2 = entry.Reserved2 }); } } finally { foreach (var reader in readers) { reader.Value?.Dispose(); } } }
public IList <Ddr573DirectoryEntry> Decode(Ddr573Image image) { return(DecodeInternal(image).ToList()); }
public IList <Ddr573File> Decode(Ddr573Image image, string dbKey) { return(DecodeInternal(image, dbKey).ToList()); }