Пример #1
0
        public static byte[] ToBytes(List <string> texts)
        {
            var writer = new DataWriter();

            WriteTexts(writer, texts);
            return(writer.ToArray());
        }
Пример #2
0
        public static void WriteJH(DataWriter writer, byte[] fileData, ushort encryptKey, bool additionalLobCompression, bool noHeader = false)
        {
            if (additionalLobCompression)
            {
                var lobWriter = new DataWriter();
                WriteLob(lobWriter, fileData, (uint)FileType.LOB);
                fileData = lobWriter.ToArray();
            }

            var encryptedData = Compression.JH.Crypt(fileData, encryptKey);

            if (!noHeader)
            {
                uint header = (uint)FileType.JH | (uint)((ushort)((uint)FileType.JH >> 16) ^ encryptKey);
                writer.Write(header);
            }

            writer.Write(encryptedData);
        }
Пример #3
0
        public static void WriteContainer(DataWriter writer, Dictionary <uint, byte[]> filesData, FileType fileType)
        {
            switch (fileType)
            {
            case FileType.AMNC:
            case FileType.AMNP:
            case FileType.AMBR:
            case FileType.AMPC:
            {
                if (filesData.Count >= 0xffff)     // -1 cause JH uses the 1-based index as a word
                {
                    throw new AmbermoonException(ExceptionScope.Data, $"In a container file there can only be {0xffff-1} files at max.");
                }

                if (filesData.ContainsKey(0))
                {
                    throw new AmbermoonException(ExceptionScope.Data, "The first file must have index 1 and not 0.");
                }

                var        writerWithoutHeader = new DataWriter();
                int        totalFileNumber     = (int)filesData.Keys.Max();
                List <int> fileSizes           = Enumerable.Repeat(0, totalFileNumber).ToList();

                foreach (var file in filesData)
                {
                    var fileData   = file.Value;
                    int prevOffset = writerWithoutHeader.Position;

                    /*
                     * AMNC | Multiple file container (data uses [JH](JH.md) encoding). The C stands for "crypted". | 0x414d4e43 ('AMNC')
                     * AMNP | Multiple file container (data uses [JH](JH.md) encoding and the files are often [LOB](LOB.md) encoded in addition). The P stands for "packed". | 0x414d4e50 ('AMNP')
                     * AMBR | Multiple file container (no encryption). The R stands for "raw". | 0x414d4252 ('AMNR')
                     * AMPC | Another multiple file container (only compressed, not JH encrypted) | 0x414d5043 ('AMPC')
                     */
                    if (fileType == FileType.AMNC)
                    {
                        WriteJH(writerWithoutHeader, fileData, (ushort)file.Key, false);
                    }
                    else if (fileType == FileType.AMBR)
                    {
                        writerWithoutHeader.Write(fileData);
                    }
                    else if (fileType == FileType.AMPC)
                    {
                        WriteLob(writerWithoutHeader, fileData);
                    }
                    else     // AMNP
                    {
                        // this may be lob compressed if size is better
                        var lobWriter = new DataWriter();
                        WriteLob(lobWriter, fileData, (uint)FileType.LOB);
                        var  data = lobWriter.Size - 4 < fileData.Length ? lobWriter.ToArray() : fileData;
                        bool lob  = data != fileData;
                        // this is always JH encoded
                        var    jhWriter = new DataWriter();
                        byte[] header   = lob ? data.Take(8).ToArray() : new byte[4] {
                            0, 0, 0, 0
                        };
                        byte[] encodedData = lob ? data.Skip(8).ToArray() : data;
                        WriteJH(jhWriter, encodedData, (ushort)file.Key, false, true);
                        writerWithoutHeader.Write(header);
                        writerWithoutHeader.Write(encodedData);
                    }

                    fileSizes[(int)file.Key - 1] = writerWithoutHeader.Position - prevOffset;
                }

                writer.Write((uint)fileType);
                writer.Write((ushort)totalFileNumber);
                fileSizes.ForEach(fileSize => writer.Write((uint)fileSize));
                writer.Write(writerWithoutHeader.ToArray());
            }
            break;

            default:
                throw new AmbermoonException(ExceptionScope.Data, $"File type '{fileType}' is no container format.");
            }
        }