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);
            }
        }
Beispiel #2
0
        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());
 }
Beispiel #4
0
 public IList <Ddr573File> Decode(Ddr573Image image, string dbKey)
 {
     return(DecodeInternal(image, dbKey).ToList());
 }