コード例 #1
0
        public void Save(String filename)
        {
            using (var bw = new BinaryWriterX(File.Create(filename)))
            {
                bw.BaseStream.Position = 0x1c;

                GetDirInfo();

                int nameListLength = 0;
                foreach (var name in dirEntries)
                {
                    nameListLength += (name.dir.Length + 1) * 2;
                }

                //Write Entry table
                int filesOffset = 0;
                int offset      = 0;
                int dataOffset  = 0x1c + dirEntries.Count * 0xc + nameListLength;
                for (int i = 0; i < dirEntries.Count; i++)
                {
                    if (dirEntries[i].dir != "." && dirEntries[i].dir.Contains('.'))
                    {
                        bw.Write(offset);
                        bw.Write(dataOffset);
                        bw.Write((uint)Files[filesOffset].FileSize.GetValueOrDefault());

                        dataOffset += (int)Files[filesOffset++].FileSize.GetValueOrDefault();
                        offset     += (dirEntries[i].dir.Length + 1) * 2;
                    }
                    else
                    {
                        bw.Write(offset | 0x01000000);
                        bw.Write(dirEntries[i].lvl);
                        bw.Write(dirEntries[i].dirCount);

                        offset += (dirEntries[i].dir.Length + 1) * 2;
                    }
                }

                //Write names
                foreach (var dir in dirEntries)
                {
                    for (int i = 0; i < dir.dir.Length; i++)
                    {
                        bw.Write((short)dir.dir[i]);
                    }
                    bw.Write((short)0);
                }

                //Write FileData
                foreach (var data in Files)
                {
                    bw.Write(new BinaryReaderX(data.FileData).ReadBytes((int)data.FileSize.GetValueOrDefault()));
                }

                //Header
                bw.BaseStream.Position = 0;
                header.fileSize        = (int)bw.BaseStream.Length;
                header.tableLength     = dirEntries.Count * 0xc + nameListLength;
                header.dataOffset      = 0x1c + dirEntries.Count * 0xc + nameListLength;
                bw.WriteStruct(header);
            }
        }
コード例 #2
0
ファイル: Common.cs プロジェクト: SeeMirra/Kuriimu
        public static byte[] Save(Bitmap bmp, ImageSettings settings)
        {
            settings.Width  = bmp.Width;
            settings.Height = bmp.Height;
            var points = GetPointSequence(settings);

            var ms          = new MemoryStream();
            var etc1encoder = new ETC1.Encoder();

            Enum.TryParse <DXT.Formats>(settings.Format.ToString(), false, out var dxtFormat);
            var dxtencoder = new DXT.Encoder(dxtFormat);

            using (var bw = new BinaryWriterX(ms))
            {
                foreach (var point in points)
                {
                    int x = Clamp(point.X, 0, bmp.Width);
                    int y = Clamp(point.Y, 0, bmp.Height);

                    var color = bmp.GetPixel(x, y);
                    if (settings.PixelShader != null)
                    {
                        color = settings.PixelShader(color);
                    }

                    switch (settings.Format)
                    {
                    case Format.L8:
                        bw.Write(color.G);
                        break;

                    case Format.A8:
                        bw.Write(color.A);
                        break;

                    case Format.LA44:
                        bw.WriteNibble(color.A / 16);
                        bw.WriteNibble(color.G / 16);
                        break;

                    case Format.LA88:
                        bw.Write(color.A);
                        bw.Write(color.G);
                        break;

                    case Format.HL88:
                        bw.Write(color.G);
                        bw.Write(color.R);
                        break;

                    case Format.RGB565:
                        bw.Write((short)((color.R / 8 << 11) | (color.G / 4 << 5) | (color.B / 8)));
                        break;

                    case Format.RGB888:
                        bw.Write(color.B);
                        bw.Write(color.G);
                        bw.Write(color.R);
                        break;

                    case Format.RGBA5551:
                        bw.Write((short)((color.R / 8 << 11) | (color.G / 8 << 6) | (color.B / 8 << 1) | color.A / 128));
                        break;

                    case Format.RGBA4444:
                        bw.WriteNibble(color.A / 16);
                        bw.WriteNibble(color.B / 16);
                        bw.WriteNibble(color.G / 16);
                        bw.WriteNibble(color.R / 16);
                        break;

                    case Format.RGBA8888:
                        bw.Write(color.A);
                        bw.Write(color.B);
                        bw.Write(color.G);
                        bw.Write(color.R);
                        break;

                    case Format.ETC1:
                    case Format.ETC1A4:
                        etc1encoder.Set(color, data =>
                        {
                            if (settings.Format == Format.ETC1A4)
                            {
                                bw.Write(data.Alpha);
                            }
                            bw.WriteStruct(data.Block);
                        });
                        break;

                    case Format.DXT1:
                    case Format.DXT5:
                        dxtencoder.Set(color, data =>
                        {
                            if (settings.Format == Format.DXT5)
                            {
                                bw.Write(data.alpha);
                            }
                            bw.Write(data.block);
                        });
                        break;

                    case Format.L4:
                        bw.WriteNibble(color.G / 16);
                        break;

                    case Format.A4:
                        bw.WriteNibble(color.A / 16);
                        break;

                    default:
                        throw new NotSupportedException();
                    }
                }
            }

            return(ms.ToArray());
        }
コード例 #3
0
        public void Save(string filename)
        {
            using (var bw = new BinaryWriterX(File.Create(filename)))
            {
                var table1Offset    = 0x10 + bmps.Count * 0x4;
                var ptgtTableOffset = table1Offset + 0x4 + table1Entries.Count * 0x4 + table1Entries.SelectMany(x => x.SelectMany(b => new[] { b })).Count();
                var imgDataSize     = (ptgtTableOffset + 0x8 + ptgtEntries.Length + 0x7f) & ~0x7f;//ptgtEntries.Count * 0x8 + ptgtEntries.Count * 0xe + 0x7f) & ~0x7f;

                //Header
                bw.Write(Encoding.ASCII.GetBytes("IOBJ"));
                bw.Write(table1Offset);
                bw.Write(ptgtTableOffset);
                bw.Write(bmps.Count);

                //Table1
                bw.BaseStream.Position = table1Offset;
                bw.Write(table1Entries.Count);
                var offset = 0x4 + table1Entries.Count * 0x4;
                foreach (var entry in table1Entries)
                {
                    bw.Write(offset);
                    offset += entry.Length;
                }
                foreach (var entry in table1Entries)
                {
                    bw.Write(entry);
                }

                //PTGT
                bw.WriteStruct(ptgtHeader);
                bw.Write(ptgtEntries);

                /*bw.Write(ptgtEntries.Count);
                 * foreach (var entry in ptgtEntries)
                 *  bw.WriteStruct(entry.offsetEntry);
                 * foreach (var entry in ptgtEntries)
                 *  foreach (var floatEntry in entry.floats)
                 *      bw.Write(floatEntry);
                 * bw.WriteAlignment(0x80);*/

                //Images
                var imgOffsets = new List <int>();
                var count      = 0;
                foreach (var bmp in bmps)
                {
                    imgOffsets.Add((int)bw.BaseStream.Position);

                    Format format;
                    using (var br = new BinaryReaderX(new MemoryStream(imgMetaInf[count])))
                        format = (Format)br.ReadInt32();

                    throw new System.NotImplementedException();
                    var settings = new ImageSettings
                    {
                        Width  = bmp.Width,
                        Height = bmp.Height,
                        //Orientation = Orientation.XFlip,
                        Format = ImageSettings.ConvertFormat(((int)format > 0x12) ? Format.ETC1A4 : format)
                    };

                    var pic = Common.Save(bmp, settings);

                    bw.Write(pic.Length);
                    bw.Write(bmp.Width);
                    bw.Write(bmp.Height);
                    bw.Write(imgMetaInf[count++]);

                    bw.Write(pic);
                    bw.WriteAlignment(0x80);
                }

                //imgOffsets in Header
                bw.BaseStream.Position = 0x10;
                foreach (var imgOff in imgOffsets)
                {
                    bw.Write(imgOff);
                }
            }
        }
コード例 #4
0
ファイル: GMD.cs プロジェクト: mhdasding/Kuriimu
        public void Save(Stream output)
        {
            using (var bw = new BinaryWriterX(output, ByteOrder))
            {
                bw.BaseStream.Position = HeaderLength + Header.NameSize + 1;

                // Section Entries
                if (Header.Version == Versions.Version1)
                {
                    foreach (var entry in EntriesV1)
                    {
                        bw.WriteStruct(entry);
                    }
                }
                else if (Header.Version == Versions.Version2)
                {
                    foreach (var entry in EntriesV2)
                    {
                        bw.WriteStruct(entry);
                    }
                }

                // Unknown Version 2 Section
                if (Header.Version == Versions.Version2)
                {
                    bw.Write(UnknownV2);
                }

                // Labels
                uint labelSize = 0;
                for (var i = 0; i < Header.LabelCount; i++)
                {
                    bw.WriteASCII(Names[i]);
                    bw.Write((byte)0);
                    labelSize += (uint)Names[i].Length + 1;
                }
                Header.LabelSize = labelSize;

                // Sections
                var textStart = bw.BaseStream.Position;

                var textS = new MemoryStream();
                using (var textW = new BinaryWriterX(textS, true))
                {
                    foreach (var label in Labels)
                    {
                        textW.Write(Encoding.UTF8.GetBytes(label.Text));
                        textW.Write((byte)0);
                    }
                }
                //ReXOR if needed, only for version 1 for now
                if (Header.Version == Versions.Version1 && IsXORed)
                {
                    var xor = new XOR(Header.Version);
                    var tmp = xor.Obfuscate(new BinaryReaderX(textS).ReadAllBytes());
                    textS.Position = 0;
                    new BinaryWriterX(textS, true).Write(tmp);
                }
                bw.Write(new BinaryReaderX(textS).ReadAllBytes());

                Header.SectionSize = (uint)(bw.BaseStream.Position - textStart);

                // Header
                bw.BaseStream.Position = 0;
                bw.WriteStruct(Header);
                bw.WriteASCII(Name);
                bw.Write((byte)0);
            }
        }
コード例 #5
0
ファイル: G1T.cs プロジェクト: mhdasding/Kuriimu
        public void Save(Stream input)
        {
            //Sanity check
            for (int i = 0; i < bmps.Count; i++)
            {
                var padWidth  = 2 << (int)Math.Log(bmps[i].Width - 1, 2);
                var padHeight = 2 << (int)Math.Log(bmps[i].Height - 1, 2);
                if (padWidth >= Math.Pow(2, 16) || padHeight >= Math.Pow(2, 16))
                {
                    throw new Exception($"Image {i} has to be smaller than {Math.Pow(2, 15)}x{Math.Pow(2, 15)}");
                }
            }

            using (BinaryWriterX bw = new BinaryWriterX(input, ByteOrder))
            {
                //Create offsetlist
                var offsetList = new List <int>();
                var off        = header.texCount * 4;
                for (int i = 0; i < header.texCount; i++)
                {
                    offsetList.Add(off);
                    off += 0x8 + ((metaExt[i] != null) ? metaExt[i].Length + 4 : 0);
                    off += bmps[i].Width * bmps[i].Height * Support.Format[meta[i].format].BitDepth / 8;
                }

                //Update meta
                for (int i = 0; i < header.texCount; i++)
                {
                    meta[i].dimension = (byte)((int)(Math.Log(bmps[i].Width - 1, 2) + 1) | ((int)(Math.Log(bmps[i].Height - 1, 2) + 1) * 16));
                }

                //Write updated data
                bw.BaseStream.Position = header.dataOffset;
                foreach (var offInt in offsetList)
                {
                    bw.Write(offInt);
                }

                //Write images
                for (int i = 0; i < bmps.Count; i++)
                {
                    bw.WriteStruct(meta[i]);
                    if (metaExt[i] != null)
                    {
                        bw.Write(metaExt[i].Length + 4);
                        bw.Write(metaExt[i]);
                    }

                    IImageSwizzle swizzle = null;
                    if (vita)
                    {
                        swizzle = new VitaSwizzle(2 << (int)Math.Log(bmps[i].Width - 1, 2), 2 << (int)Math.Log(bmps[i].Height - 1, 2), Support.Format[meta[i].format].FormatName.Contains("DXT"));
                    }
                    else if (Support.Format[meta[i].format].FormatName.Contains("DXT"))
                    {
                        swizzle = new BlockSwizzle(2 << (int)Math.Log(bmps[i].Width - 1, 2), 2 << (int)Math.Log(bmps[i].Height - 1, 2));
                    }

                    var setting = new ImageSettings
                    {
                        Width       = 2 << (int)Math.Log(bmps[i].Width - 1, 2),
                            Height  = 2 << (int)Math.Log(bmps[i].Height - 1, 2),
                            Swizzle = swizzle,
                            Format  = Support.Format[meta[i].format]
                    };
                    bw.Write(Common.Save(bmps[i], setting));
                }
                header.fileSize = (int)bw.BaseStream.Length;

                //Header
                bw.BaseStream.Position = 0;
                bw.WriteStruct(header);
            }
        }
コード例 #6
0
        private void SaveSystemGar(Stream input)
        {
            int Align(int value, int align) => value + (align - 1) & ~(align - 1);

            using (var bw = new BinaryWriterX(input))
            {
                var files = Files.OrderBy(x => x.ext.Length).ToList();

                //get Extension and their count
                Dictionary <string, int> exts = new Dictionary <string, int>();
                foreach (var file in files)
                {
                    var ext = Path.GetExtension(file.FileName).Replace(".", "");
                    if (!exts.ContainsKey(ext))
                    {
                        exts.Add(ext, 1);
                    }
                    else
                    {
                        exts[ext]++;
                    }
                }

                //get offsets
                int chunkExtNameOffset  = _header.chunkEntryOffset + (exts.Count + 1) * 0x20;
                int chunkSubTableOffset = Align(chunkExtNameOffset + Encoding.ASCII.GetByteCount("unknown\0") + exts.Aggregate(0, (a, b) => a + Encoding.ASCII.GetByteCount(b.Key) + 1), 4);
                int chunkInfoOffset     = chunkSubTableOffset + sysEntriesSubTable.Length;
                int chunkInfoNameOffset = chunkInfoOffset + Files.Count * 0x10;
                int dataOffset          = Align(chunkInfoNameOffset + Files.Aggregate(0, (a, b) => a + Encoding.ASCII.GetByteCount(Path.GetFileName(b.FileName)) + 1), 0x80);

                bw.BaseStream.Position = 0x20;

                //Write chunkEntries
                int localChunkNameOffset = chunkExtNameOffset;

                //Add "unknown" chunk Entry
                bw.Write(0);
                bw.Write(0x4);
                bw.Write(0xFFFFFFFF);
                bw.Write(localChunkNameOffset);
                bw.Write(0xFFFFFFFF);
                bw.BaseStream.Position += 0xC;

                localChunkNameOffset += Encoding.ASCII.GetByteCount("unknown\0");

                //Add all other chunk entries
                int filesAdded = 0;
                foreach (var ext in exts)
                {
                    bw.Write(ext.Value);
                    bw.Write(sysEntries.FirstOrDefault(x => x.name == ext.Key)?.unk1 ?? 0x4);
                    bw.Write(filesAdded);
                    bw.Write(localChunkNameOffset);
                    bw.Write(sysEntries.FirstOrDefault(x => x.name == ext.Key)?.subTableOffset ?? 0x0);
                    bw.BaseStream.Position += 0xC;

                    filesAdded           += ext.Value;
                    localChunkNameOffset += Encoding.ASCII.GetByteCount(ext.Key) + 1;
                }

                //Add chunk Extensions
                bw.WriteASCII("unknown\0");
                foreach (var ext in exts)
                {
                    bw.WriteASCII(ext.Key + "\0");
                }
                bw.WriteAlignment(4);

                //Add subtable
                bw.Write(sysEntriesSubTable);

                //Write chunkInfos and Files
                var localChunkInfoOffset     = chunkInfoOffset;
                var localChunkInfoNameOffset = chunkInfoNameOffset;
                var localDataOffset          = dataOffset;
                foreach (var ext in exts)
                {
                    var filesToAdd = Files.Where(x => x.ext == ext.Key);
                    foreach (var toAdd in filesToAdd)
                    {
                        bw.BaseStream.Position = localChunkInfoOffset;
                        bw.Write((int)toAdd.FileSize);
                        bw.Write(localDataOffset);
                        bw.Write(localChunkInfoNameOffset);
                        bw.Write(0xFFFFFFFF);

                        bw.BaseStream.Position = localChunkInfoNameOffset;
                        bw.WriteASCII(Path.GetFileNameWithoutExtension(toAdd.FileName) + "\0");

                        bw.BaseStream.Position = localDataOffset;
                        toAdd.FileData.CopyTo(bw.BaseStream);

                        localDataOffset          += (int)toAdd.FileSize;
                        localChunkInfoNameOffset += Encoding.ASCII.GetByteCount(Path.GetFileNameWithoutExtension(toAdd.FileName)) + 1;
                        localChunkInfoOffset     += 0x10;
                    }
                }

                //Header
                bw.BaseStream.Position = 0;
                _header.fileSize       = (uint)bw.BaseStream.Length;
                _header.fileChunks     = (short)(exts.Count + 1);
                _header.fileCount      = (short)files.Count;
                _header.chunkInfOffset = chunkInfoOffset;
                _header.offset3        = dataOffset;
                bw.WriteStruct(_header);
            }
        }
コード例 #7
0
ファイル: CTPK.cs プロジェクト: wabberz/Kuriimu
        public void Save(Stream output)
        {
            int Pad128(int n) => (n + 127) & ~127;

            using (var bw = new BinaryWriterX(output))
            {
                //get nameList Length
                int nameListLength = (Files.Sum(afi => afi.FileName.Length + 1) + 3) & ~3;

                //Offsets
                int nameOffset = (Files.Count + 1) * 0x20 + Files.Count * 0x4;

                //Header
                bw.WriteStruct(new Header
                {
                    texCount       = (short)Files.Count,
                    texSecOffset   = Pad128(nameOffset + nameListLength + Files.Count * 12),
                    texSecSize     = (int)Files.Sum(afi => afi.FileSize),
                    crc32SecOffset = nameOffset + nameListLength,
                    texInfoOffset  = nameOffset + nameListLength + Files.Count * 0x8
                });

                //entryList
                int dataOffset = 0;
                foreach (var afi in Files)
                {
                    dataOffset = Pad128(dataOffset);
                    var entry = afi.Entry;
                    entry.texDataSize = (int)afi.FileData.Length;
                    entry.nameOffset  = nameOffset;
                    entry.texOffset   = dataOffset;
                    bw.WriteStruct(entry);
                    nameOffset += afi.FileName.Length + 1;
                    dataOffset += (int)afi.FileSize;
                }

                //texInfo 1 List
                foreach (var afi in Files)
                {
                    bw.Write((int)afi.FileData.Length);
                }

                //nameList
                foreach (var afi in Files)
                {
                    bw.WriteASCII(afi.FileName + '\0');
                }
                while (bw.BaseStream.Position % 4 != 0)
                {
                    bw.BaseStream.Position++;
                }

                //crc32List
                foreach (var afi in Files)
                {
                    bw.Write(afi.hashEntry.crc32); bw.Write(afi.hashEntry.entryNr);
                }

                //texInfo 2 List
                foreach (var afi in Files)
                {
                    bw.Write(afi.texInfo);
                }

                //Write data
                foreach (var afi in Files)
                {
                    bw.Write(new byte[Pad128((int)bw.BaseStream.Length) - (int)bw.BaseStream.Length]);
                    afi.FileData.CopyTo(bw.BaseStream);
                }
            }
        }
コード例 #8
0
ファイル: CTPK.cs プロジェクト: getov/Kuriimu
        public void Save(String filename)
        {
            if (isRaw)
            {
                SaveRaw(filename);
            }
            else
            {
                using (BinaryWriterX bw = new BinaryWriterX(File.Create(filename)))
                {
                    var settings = new ImageSettings
                    {
                        Width         = bmp.Width,
                        Height        = bmp.Height,
                        Format        = ImageSettings.ConvertFormat(entries[0].imageFormat),
                        PadToPowerOf2 = false
                    };
                    byte[] resBmp = Common.Save(bmp, settings);

                    int diff = resBmp.Length - entries[0].texDataSize;
                    entries[0].width       = (short)bmp.Width;
                    entries[0].height      = (short)bmp.Height;
                    entries[0].texDataSize = resBmp.Length;
                    for (int i = 1; i < header.texCount; i++)
                    {
                        entries[i].texOffset -= diff;
                    }

                    texSizeList[0] = resBmp.Length;

                    //write entries
                    bw.BaseStream.Position = 0x20;
                    for (int i = 0; i < header.texCount; i++)
                    {
                        bw.WriteStruct(entries[i]);
                    }

                    //write texSizeInfo
                    for (int i = 0; i < header.texCount; i++)
                    {
                        bw.Write(texSizeList[i]);
                    }

                    //write names
                    for (int i = 0; i < header.texCount; i++)
                    {
                        bw.WriteASCII(nameList[i]);
                        bw.Write((byte)0);
                    }

                    //write hashes
                    crc32List = crc32List.OrderBy(e => e.crc32).ToList();
                    bw.BaseStream.Position = header.crc32SecOffset;
                    for (int i = 0; i < header.texCount; i++)
                    {
                        bw.Write(crc32List[i].crc32);
                        bw.Write(crc32List[i].entryNr);
                    }

                    //write texInfo
                    bw.BaseStream.Position = header.texInfoOffset;
                    for (int i = 0; i < header.texCount; i++)
                    {
                        bw.Write(texInfoList2[i]);
                    }

                    //write texData
                    bw.BaseStream.Position = header.texSecOffset;
                    bw.Write(resBmp);
                    bw.Write(rest);

                    header.texSecSize      = (int)bw.BaseStream.Length - header.texSecOffset;
                    bw.BaseStream.Position = 0;
                    bw.WriteStruct(header);
                }
            }
        }
コード例 #9
0
        public void Save(string filename)
        {
            // Write file data and remember the relative offsets
            var fileData    = new MemoryStream();
            var fileOffsets = new List <int>();

            foreach (var file in Files)
            {
                fileData.Position = (fileData.Position + 0x1F) & ~0x1F;

                fileOffsets.Add((int)fileData.Position);

                file.FileData.Position = 0;
                file.FileData.CopyTo(fileData);
            }

            // It seems the file data portion in itself is aligned to 0x20
            while (fileData.Position % 0x20 != 0)
            {
                fileData.WriteByte(0);
            }

            using (var bw = new BinaryWriterX(File.OpenWrite(filename)))
            {
                // Write table information
                bw.BaseStream.Position = header.headerSize;

                // Write file offsets last, due to their relative property to the following tables
                bw.BaseStream.Position += Files.Count * 0x4;
                foreach (var file in Files)
                {
                    bw.Write((int)file.FileSize);
                }

                foreach (var file in Files)
                {
                    bw.Write(Crc32.Create(file.FileName));
                }

                foreach (var unkId in _unkIds)
                {
                    bw.Write(unkId);
                }
                bw.WriteAlignment(4);

                var stringRelativeOffset = (Files.Count * 2 + 3) & ~3;
                foreach (var file in Files)
                {
                    bw.Write((short)stringRelativeOffset);
                    stringRelativeOffset += Encoding.ASCII.GetByteCount(file.FileName) + 1;
                }
                bw.WriteAlignment(4);

                foreach (var file in Files)
                {
                    bw.WriteASCII(file.FileName + '\0');
                }
                bw.WriteAlignment();

                bw.BaseStream.Position = 0x40;
                foreach (var offset in fileOffsets)
                {
                    bw.Write((int)((offset + bw.BaseStream.Length - 0x40) >> 2));
                }

                // Write file data
                bw.BaseStream.Position = bw.BaseStream.Length;
                fileData.Position      = 0;
                fileData.CopyTo(bw.BaseStream);

                // Create header
                var newHeader = new Header
                {
                    contentSize      = (int)bw.BaseStream.Length - 0x40,
                    fileCount        = Files.Count,
                    table2EntryCount = (short)Files.Count,
                    table3EntryCount = (short)(Files.Count * 2),
                    unk2             = header.unk2,
                    unk3             = header.unk3
                };
                bw.BaseStream.Position = 0;
                bw.WriteStruct(newHeader);
            }
        }
コード例 #10
0
        public void Save(Stream output)
        {
            using (BinaryWriterX bw = new BinaryWriterX(output))
            {
                bw.BaseStream.Position = 0x48;

                //first unknown half of info section
                bw.Write(unk1);
                bw.Write(unk2);

                //entryList and Data
                uint dataOffset    = 0;
                uint movDataOffset = (uint)(0x48 + unk1.Length + unk2.Length + Files.Count * 0x10);
                foreach (var name in dirStruct)
                {
                    movDataOffset += 1 + (uint)Encoding.GetEncoding("SJIS").GetBytes((name.Last() != '/') ? name.Split('/').Last() : name).Length;
                }
                while (movDataOffset % 4 != 0)
                {
                    movDataOffset++;
                }

                header.dataOffset  = movDataOffset;
                header.nameOffset  = (uint)(0x48 + unk1.Length + unk2.Length + Files.Count * 0x10);
                header.folderCount = (short)folderCounts.Count;
                header.fileCount   = Files.Count;
                header.fileCount2  = Files.Count;

                int pos = 0;
                foreach (var folderCount in folderCounts)
                {
                    var nameSorted = new List <NameEntry>();
                    for (int i = 0; i < folderCount; i++)
                    {
                        nameSorted.Add(new NameEntry {
                            name = Files[pos + i].FileName, crc32 = Files[pos + i].crc32, size = (uint)Files[pos + i].FileSize
                        });
                    }
                    nameSorted = nameSorted.OrderBy(x => x.name, StringComparer.OrdinalIgnoreCase).ToList();

                    var  entriesTmp = new List <Entry>();
                    uint nameOffset = 0;
                    for (int i = 0; i < folderCount; i++)
                    {
                        entriesTmp.Add(new Entry {
                            crc32 = Files[pos + i].crc32
                        });
                    }
                    for (int i = 0; i < folderCount; i++)
                    {
                        var foundEntry = entriesTmp.Find(x => x.crc32 == nameSorted[i].crc32);
                        foundEntry.nameOffsetInFolder = nameOffset;
                        foundEntry.fileOffset         = dataOffset;
                        foundEntry.fileSize           = nameSorted[i].size;

                        var t = "";
                        if (bw.BaseStream.Position == 0x74fc)
                        {
                            t = nameSorted[i].name;
                        }
                        t = "";

                        nameOffset += 1 + (uint)nameSorted[i].name.Split('/').Last().Length;

                        long bk = bw.BaseStream.Position;
                        bw.BaseStream.Position = movDataOffset;
                        Files.Find(x => x.FileName == nameSorted[i].name).FileData.CopyTo(bw.BaseStream);
                        bw.BaseStream.Position++;
                        while (bw.BaseStream.Position % 4 != 0)
                        {
                            bw.BaseStream.Position++;
                        }
                        dataOffset            += (uint)bw.BaseStream.Position - movDataOffset;
                        movDataOffset          = (uint)bw.BaseStream.Position;
                        bw.BaseStream.Position = bk;
                    }
                    for (int i = 0; i < folderCount; i++)
                    {
                        bw.WriteStruct(entriesTmp[i]);
                    }

                    pos += folderCount;
                }


                //nameList
                foreach (var name in dirStruct)
                {
                    bw.Write((byte)0);
                    if (name.Last() != '/')
                    {
                        bw.Write(Encoding.GetEncoding("SJIS").GetBytes(name.Split('/').Last()));
                    }
                    else
                    {
                        bw.Write(Encoding.GetEncoding("SJIS").GetBytes(name));
                    }
                }
                bw.BaseStream.Position++;
                while (bw.BaseStream.Position % 4 != 0)
                {
                    bw.BaseStream.Position++;
                }

                //Write Header
                bw.BaseStream.Position = 0;
                bw.WriteStruct(header);
            }
        }
コード例 #11
0
        public void Save(Stream output)
        {
            using (var bw = new BinaryWriterX(output))
            {
                var newHeight      = bmps[0].Height;
                var newWidth       = bmps[0].Width;
                var newMipMapCount = headerInfo.mipMapCount;
                if (headerInfo.mipMapCount > 1)
                {
                    if (bmps[0].Width >= bmps[0].Height)
                    {
                        newWidth  = 2 << (int)Math.Log(bmps[0].Width - 1, 2);
                        newHeight = (int)(newWidth / (bmps[0].Width / bmps[0].Height));
                    }
                    else
                    {
                        newHeight = 2 << (int)Math.Log(bmps[0].Height - 1, 2);
                        newWidth  = (int)(newHeight / (bmps[0].Height / bmps[0].Width));
                    }
                    newMipMapCount = ((int)Math.Log(Math.Max(newWidth, newHeight), 2) + 1);
                }

                header.Block1 = (uint)((ushort)headerInfo.version | (headerInfo.format << 16) | (headerInfo.unk1 << 24));
                header.Block2 = (uint)((headerInfo.r1 << 4) | (headerInfo.unk2));
                header.Block3 = (uint)((newMipMapCount << 26) | (newHeight << 13) | (ushort)newWidth);
                bw.WriteStruct(header);

                if (headerInfo.format == 0xc)
                {
                    bw.BaseStream.Position = 0x10 + 3 * 2 * 0x4;

                    var texOffsets = new List <uint>();
                    var texSizes   = new List <uint>();

                    for (int i = 0; i < bmps.Count; i++)
                    {
                        settings = new ImageSettings
                        {
                            Width  = bmps[i].Width,
                            Height = bmps[i].Height
                        };

                        if (i == 0)
                        {
                            settings.Format  = new DXT(DXT.Version.DXT5);
                            settings.Swizzle = new BlockSwizzle(settings.Width, settings.Height);
                        }
                        else if (i == 1)
                        {
                            settings.Format = new PVRTC(PVRTC.Format.PVRTCA_4bpp);
                            (settings.Format as PVRTC)._width  = settings.Width;
                            (settings.Format as PVRTC)._height = settings.Height;
                            settings.Swizzle = null;
                        }
                        else
                        {
                            settings.Format  = new ATC(true, Kontract.Image.Support.ATC.AlphaMode.Interpolated);
                            settings.Swizzle = new BlockSwizzle(settings.Width, settings.Height);
                        }

                        var texData = Common.Save(bmps[i], settings);

                        texOffsets.Add((uint)bw.BaseStream.Position);
                        texSizes.Add((uint)texData.Length);

                        bw.Write(texData);
                    }

                    bw.BaseStream.Position = 0x10;
                    foreach (var offset in texOffsets)
                    {
                        bw.Write(offset);
                    }
                    foreach (var size in texSizes)
                    {
                        bw.Write(size);
                    }
                }
                else
                {
                    var settings = new ImageSettings
                    {
                        Format = Support.Format[headerInfo.format]
                    };

                    bw.BaseStream.Position = 0x28;
                    for (int i = 0; i < newMipMapCount; i++)
                    {
                        settings.Width  = Math.Max(newWidth >> i, 1);
                        settings.Height = Math.Max(newHeight >> i, 1);

                        if (Support.Format[headerInfo.format].FormatName.Contains("DXT") || settings.Format.FormatName.Contains("ETC"))
                        {
                            settings.Swizzle = new BlockSwizzle(newWidth >> i, newHeight >> i);
                        }

                        bw.Write(Common.Save(bmps[0].Resize(settings.Width, settings.Height), settings));
                    }

                    bw.BaseStream.Position = 0x10;
                    for (int i = 0; i < 3; i++)
                    {
                        bw.Write(0x28);
                    }
                }
            }
        }
コード例 #12
0
        public void Save(string filename)
        {
            long bk;

            using (var bw = new BinaryWriterX(File.Create(filename)))
            {
                bw.WriteStruct(cfgHeader);

                for (int j = 0; j < editorEntries.Count; j++)
                {
                    if (j > 0)
                    {
                        EditorStruct bk2 = editorEntries[j];

                        var success1 = (cfgHeader.dataOffset > bw.BaseStream.Length) ? bk2.entryOffset = 0 : bk2.entryOffset = (uint)bw.BaseStream.Length - cfgHeader.dataOffset;

                        bk = bw.BaseStream.Position;
                        var success2 = (cfgHeader.dataOffset > bw.BaseStream.Length) ? bw.BaseStream.Position = cfgHeader.dataOffset : bw.BaseStream.Position = bw.BaseStream.Length;
                        bw.Write(Encoding.GetEncoding("shift-jis").GetBytes(Labels[labelCount++].Text));
                        bw.Write((byte)0x00);
                        bw.BaseStream.Position = bk;

                        editorEntries[j] = bk2;
                    }

                    bw.WriteStruct <EditorStruct>(editorEntries[j]);
                }

                if (editorRest != null)
                {
                    bw.Write(editorRest);
                }
                else
                {
                    for (int j = 0; j < textEntries.Count; j++)
                    {
                        if (j > 0 && textEntries[j].entryOffset != 0xFFFFFFFF)
                        {
                            TextStruct bk2 = textEntries[j];

                            var success1 = (cfgHeader.dataOffset > bw.BaseStream.Length) ? bk2.entryOffset = 0 : bk2.entryOffset = (uint)bw.BaseStream.Length - cfgHeader.dataOffset;

                            bk = bw.BaseStream.Position;
                            var success2 = (cfgHeader.dataOffset > bw.BaseStream.Length) ? bw.BaseStream.Position = cfgHeader.dataOffset : bw.BaseStream.Position = bw.BaseStream.Length;
                            bw.Write(Encoding.GetEncoding("shift-jis").GetBytes(Labels[labelCount++].Text));
                            bw.Write((byte)0x00);
                            bw.BaseStream.Position = bk;

                            textEntries[j] = bk2;
                        }

                        bw.WriteStruct(textEntries[j]);
                    }
                    if (textRest != null)
                    {
                        bw.Write(textRest);
                    }
                }

                bw.BaseStream.Position = 0x8;
                bw.Write((int)(bw.BaseStream.Length - cfgHeader.dataOffset));

                bw.BaseStream.Position = bw.BaseStream.Length;
                bw.WriteAlignment(0x10, 0xff);
            }
        }
コード例 #13
0
        public BinaryReaderX createCfg(int part)
        {
            long bk;

            BinaryWriterX br = new BinaryWriterX(new MemoryStream());

            br.WriteStruct <Header>(headerList[part]);

            for (int j = 0; j < editorEntries[part].Count; j++)
            {
                if (j > 0)
                {
                    EditorStruct bk2 = editorEntries[part][j];

                    var success1 = (headerList[part].dataOffset > br.BaseStream.Length) ? bk2.entryOffset = 0 : bk2.entryOffset = (uint)br.BaseStream.Length - headerList[part].dataOffset;

                    bk = br.BaseStream.Position;
                    var success2 = (headerList[part].dataOffset > br.BaseStream.Length) ? br.BaseStream.Position = headerList[part].dataOffset : br.BaseStream.Position = br.BaseStream.Length;
                    br.Write(Encoding.GetEncoding("shift-jis").GetBytes(Labels[labelCount++].Text));
                    br.Write((byte)0x00);
                    br.BaseStream.Position = bk;

                    editorEntries[part][j] = bk2;
                }

                br.WriteStruct <EditorStruct>(editorEntries[part][j]);
            }

            if (editorRest[part] != null)
            {
                br.Write(editorRest[part]);
            }
            else
            {
                for (int j = 0; j < textEntries[part].Count; j++)
                {
                    if (j > 0 && textEntries[part][j].entryOffset != 0xFFFFFFFF)
                    {
                        TextStruct bk2 = textEntries[part][j];

                        var success1 = (headerList[part].dataOffset > br.BaseStream.Length) ? bk2.entryOffset = 0 : bk2.entryOffset = (uint)br.BaseStream.Length - headerList[part].dataOffset;

                        bk = br.BaseStream.Position;
                        var success2 = (headerList[part].dataOffset > br.BaseStream.Length) ? br.BaseStream.Position = headerList[part].dataOffset : br.BaseStream.Position = br.BaseStream.Length;
                        br.Write(Encoding.GetEncoding("shift-jis").GetBytes(Labels[labelCount++].Text));
                        br.Write((byte)0x00);
                        br.BaseStream.Position = bk;

                        textEntries[part][j] = bk2;
                    }

                    br.WriteStruct <TextStruct>(textEntries[part][j]);
                }
                if (textRest[part] != null)
                {
                    br.Write(textRest[part]);
                }
            }

            br.BaseStream.Position = 0x8;
            br.Write((int)(br.BaseStream.Length - headerList[part].dataOffset));

            br.BaseStream.Position = br.BaseStream.Length;
            while (br.BaseStream.Position % 16 != 0)
            {
                br.Write((byte)0xFF);
            }

            return(new BinaryReaderX(br.BaseStream));
        }
コード例 #14
0
ファイル: SARC.cs プロジェクト: shenhaiyu/Kuriimu
        public void Save(Stream output, bool leaveOpen = false)
        {
            using (var bw = new BinaryWriterX(output, leaveOpen, byteOrder))
            {
                //Create SARCHeader
                var header = new SARCHeader
                {
                    byteOrder  = byteOrder,
                    dataOffset = Files.Aggregate(
                        0x14 + 0xc + 0x8 + Files.Sum(afi => usesSFNT ? ((afi.FileName.Length + 4) & ~3) + 0x10 : 0x10),
                        (n, file) => Support.Pad(n, file.FileName, (byteOrder == ByteOrder.LittleEndian) ? System.CTR : System.WiiU))
                };

                //SFATHeader
                bw.BaseStream.Position = 0x14;
                bw.WriteStruct(new SFATHeader
                {
                    hashMultiplier = (int)hashMultiplier,
                    nodeCount      = (short)Files.Count
                });

                //SFAT List + nameList
                int nameOffset = 0;
                int dataOffset = 0;
                foreach (var afi in Files)
                {
                    dataOffset = Support.Pad(dataOffset, afi.FileName, (byteOrder == ByteOrder.LittleEndian) ? System.CTR : System.WiiU);
                    var fileLen = (int)afi.FileData.Length;

                    var sfatEntry = new SFATEntry
                    {
                        nameHash       = usesSFNT ? SimpleHash.Create(afi.FileName, hashMultiplier) : Convert.ToUInt32(afi.FileName.Substring(2, 8), 16),
                        SFNTOffsetFlag = (uint)(((usesSFNT ? 0x100 : 0) << 16) | (usesSFNT ? nameOffset / 4 : 0)),
                        dataStart      = dataOffset,
                        dataEnd        = dataOffset + fileLen
                    };
                    bw.WriteStruct(sfatEntry);
                    nameOffset = (nameOffset + afi.FileName.Length + 4) & ~3;
                    dataOffset = sfatEntry.dataEnd;
                }

                //SFNT
                bw.WriteStruct(new SFNTHeader());
                if (usesSFNT)
                {
                    foreach (var afi in Files)
                    {
                        bw.WriteASCII(afi.FileName + "\0");
                        bw.BaseStream.Position = (bw.BaseStream.Position + 3) & ~3;
                    }
                }

                //FileData
                bw.WriteAlignment(header.dataOffset);
                foreach (var afi in Files)
                {
                    bw.WriteAlignment(Support.Pad((int)bw.BaseStream.Length, afi.FileName, (byteOrder == ByteOrder.LittleEndian) ? System.CTR : System.WiiU));    //(unusual) padding scheme through filenames
                    afi.FileData.CopyTo(bw.BaseStream);
                }

                bw.BaseStream.Position = 0;
                header.fileSize        = (int)bw.BaseStream.Length;
                bw.WriteStruct(header);
            }
        }
コード例 #15
0
        public void Save(Stream output)
        {
            void Align(Stream input) => input.Position      = (input.Position + (mediaUnitSize - 1)) & ~(mediaUnitSize - 1);
            void RomFSAlign(Stream input) => input.Position = (input.Position + (0x1000 - 1)) & ~(0x1000 - 1);

            output.Seek(ncchHeaderSize, SeekOrigin.Begin);

            ncchHeader.rsa2048 = new byte[0x100];

            if (exHeader != null)
            {
                var exHFile = Files.Where(f => f.FileName == "ExHeader.bin").First();
                ncchHeader.exHeaderSize = (int)exHFile.FileSize;
                ncchHeader.exHeaderHash = Kontract.Hash.SHA256.Create(exHFile.FileData);

                exHFile.FileData.CopyTo(output);
                Align(output);
            }

            if (plainRegion != null)
            {
                var plRFile = Files.Where(f => f.FileName == "PlainRegion.bin").First();
                ncchHeader.plainRegionOffset = (int)Math.Ceiling((double)output.Position / mediaUnitSize);
                ncchHeader.plainRegionSize   = (int)Math.Ceiling((double)plRFile.FileSize / mediaUnitSize);

                plRFile.FileData.CopyTo(output);
                Align(output);
            }

            if (logoRegion != null)
            {
                var loRFile = Files.Where(f => f.FileName == "Logo.icn").First();
                ncchHeader.plainRegionOffset = (int)Math.Ceiling((double)output.Position / mediaUnitSize);
                ncchHeader.plainRegionSize   = (int)Math.Ceiling((double)loRFile.FileSize / mediaUnitSize);

                loRFile.FileData.CopyTo(output);
                Align(output);
            }

            if (exeFS != null)
            {
                var exeFSOffset = output.Position;
                var exeFSSize   = ExeFSBuilder.Rebuild(output, Files.Where(f => f.FileName.StartsWith("ExeFS\\")).Select(f => (ExeFSFileInfo)f).ToList(), "ExeFS\\");

                ncchHeader.exeFSOffset         = (int)Math.Ceiling((double)exeFSOffset / mediaUnitSize);
                ncchHeader.exeFSSize           = (int)Math.Ceiling((double)exeFSSize / mediaUnitSize);
                ncchHeader.exeFSSuperBlockHash = Kontract.Hash.SHA256.Create(output, exeFSOffset, ExeFS.exeFSHeaderSize);

                RomFSAlign(output);
            }

            if (romFS != null)
            {
                var romFSOffset = output.Position;
                var romFSSize   = RomFSBuilder.Rebuild(output, romFSOffset, Files.Where(f => f.FileName.StartsWith("RomFS\\")).ToList(), "RomFS\\");

                ncchHeader.romFSOffset         = (int)Math.Ceiling((double)romFSOffset / mediaUnitSize);
                ncchHeader.romFSSize           = (int)Math.Ceiling((double)romFSSize / mediaUnitSize);
                ncchHeader.romFSHashRegSize    = (int)Math.Ceiling((double)RomFSBuilder.SuperBlockSize / mediaUnitSize);
                ncchHeader.romFSSuperBlockHash = RomFSBuilder.SuperBlockHash;

                output.Position = romFSOffset + romFSSize;
                Align(output);
            }

            //Header
            output.Seek(0, SeekOrigin.Begin);
            using (var bw = new BinaryWriterX(output))
                bw.WriteStruct(ncchHeader);
        }
コード例 #16
0
        public void Save(string filename)
        {
            var parStr = new List <byte[]>();

            foreach (var label in Labels)
            {
                parStr.Add(ParseString(label.Text));
            }

            using (BinaryWriterX bw = new BinaryWriterX(File.Create(filename), byteOrder))
            {
                bw.BaseStream.Position = headerSize;

                //INF1
                bw.Write(Encoding.ASCII.GetBytes("INF1"));
                bw.Write((0x10 + items.Count * (0x4 + items[0].attr.Length) + align) & ~align);
                bw.Write((short)items.Count);
                bw.Write((short)(0x4 + items[0].attr.Length));
                bw.BaseStream.Position += 4;

                var strOffset = items[0].strOffset;
                for (int i = 0; i < items.Count; i++)
                {
                    bw.Write(strOffset);
                    bw.Write(items[i].attr);
                    strOffset += parStr[i].Length;
                }

                bw.WriteAlignment(align + 1);

                //DAT1
                bw.Write(Encoding.ASCII.GetBytes("DAT1"));
                bw.Write((0x8 + items[0].strOffset + parStr.Aggregate(0, (o, i) => o += i.Length) + align) & ~align);
                bw.Write(new byte[items[0].strOffset]);

                foreach (var str in parStr)
                {
                    bw.Write(str);
                }

                bw.WriteAlignment(align + 1);

                //MID1
                if (midUsed)
                {
                    bw.Write(Encoding.ASCII.GetBytes("MID1"));
                    bw.Write((0x10 + Labels.Count * 0x4 + align) & ~align);
                    bw.Write((short)Labels.Count);
                    bw.Write(midUnk1);
                    bw.BaseStream.Position += 4;

                    foreach (var label in Labels)
                    {
                        bw.Write(label.TextID);
                    }

                    bw.WriteAlignment(align + 1);
                }

                //Header
                bw.BaseStream.Position = 0;
                header.fileSize        = (int)bw.BaseStream.Length;
                bw.WriteStruct(header);
            }
        }
コード例 #17
0
        private void SaveZeldaGar(Stream input)
        {
            using (var bw = new BinaryWriterX(input))
            {
                var files = Files.OrderBy(x => x.ext.Length).ToList();

                //get Extension and their count
                List <string> exts      = new List <string>();
                List <int>    extsCount = new List <int>();
                foreach (var file in files)
                {
                    if (!exts.Contains(Path.GetExtension(file.FileName).Split('.')[1]))
                    {
                        exts.Add(Path.GetExtension(file.FileName).Split('.')[1]);
                        extsCount.Add(1);
                    }
                    else
                    {
                        extsCount[exts.FindIndex(x => x == Path.GetExtension(file.FileName).Split('.')[1])]++;
                    }
                }

                //get offsets
                int chunkIDOffset  = 0x20 + (exts.Count + 1) * 0x10;
                int chunkInfOffset = chunkIDOffset + 8 + files.Count * 0x4;
                for (int i = 0; i < exts.Count; i++)
                {
                    chunkInfOffset += (exts[i].Length + 1);
                    while (chunkInfOffset % 4 != 0)
                    {
                        chunkInfOffset++;
                    }
                }
                int nameOffset    = chunkInfOffset + files.Count * 0xc;
                int offListOffset = nameOffset;
                for (int i = 0; i < files.Count; i++)
                {
                    offListOffset += files[i].FileName.Length + 1;
                    offListOffset += files[i].FileName.Split('.')[0].Length + 1;
                    while (offListOffset % 4 != 0)
                    {
                        offListOffset++;
                    }
                }
                int dataOffset = offListOffset + files.Count * 0x4;

                bw.BaseStream.Position = 0x20;

                //write chunkEntries
                int tmp = chunkIDOffset;
                for (int i = 0; i <= exts.Count; i++)
                {
                    if (i == 0)
                    {
                        bw.Write(0);
                        bw.Write(0xFFFFFFFF);
                        bw.Write(tmp);
                        bw.Write(0xFFFFFFFF);
                        tmp += 8;
                    }
                    else
                    {
                        bw.Write(extsCount[i - 1]);
                        bw.Write(tmp);
                        bw.Write(tmp + extsCount[i - 1] * 4);
                        bw.Write(0xFFFFFFFF);

                        var padding = 0;
                        while ((exts[i - 1].Length + 1 + padding) % 4 != 0)
                        {
                            padding++;
                        }
                        tmp += extsCount[i - 1] * 4 + exts[i - 1].Length + 1 + padding;
                    }
                }

                //write chunkIDs and magics
                int id = 0;
                for (int i = 0; i <= exts.Count; i++)
                {
                    if (i == 0)
                    {
                        bw.WriteASCII("unknown");
                        bw.Write((byte)0);
                    }
                    else
                    {
                        for (int j = 0; j < extsCount[i - 1]; j++)
                        {
                            bw.Write(id++);
                        }

                        bw.WriteASCII(exts[i - 1]);
                        bw.Write((byte)0);
                        while (bw.BaseStream.Position % 4 != 0)
                        {
                            bw.BaseStream.Position++;
                        }
                    }
                }

                //write chunkInfos
                tmp = nameOffset;
                foreach (var file in files)
                {
                    bw.Write((uint)file.FileSize);
                    bw.Write(tmp + file.FileName.Length + 1);
                    bw.Write(tmp);
                    tmp += file.FileName.Length + 1 + file.FileName.Split('.')[0].Length + 1;
                    while (tmp % 4 != 0)
                    {
                        tmp++;
                    }
                }

                //write names
                foreach (var file in files)
                {
                    bw.WriteASCII(file.FileName);
                    bw.Write((byte)0);
                    bw.WriteASCII(file.FileName.Split('.')[0]);
                    bw.Write((byte)0);
                    while (bw.BaseStream.Position % 4 != 0)
                    {
                        bw.BaseStream.Position++;
                    }
                }

                //write offsets
                tmp = dataOffset;
                foreach (var file in files)
                {
                    bw.Write(tmp);
                    tmp += (int)file.FileSize;
                }

                //write fileData
                foreach (var file in files)
                {
                    file.FileData.CopyTo(bw.BaseStream);
                }

                //Header
                bw.BaseStream.Position = 0;
                _header.fileSize       = (uint)bw.BaseStream.Length;
                _header.fileChunks     = (short)(exts.Count + 1);
                _header.fileCount      = (short)files.Count;
                _header.chunkInfOffset = chunkInfOffset;
                _header.offset3        = offListOffset;
                bw.WriteStruct(_header);
            }
        }
コード例 #18
0
ファイル: CIA.cs プロジェクト: SkipperGames/Kuriimu
        public void Save(Stream output)
        {
            var files = Files.Where(f => f.State != ArchiveFileState.Deleted).ToList();

            //Update content Indeces
            ciaHeader.contentIndex = new byte[0x2000];
            for (int i = 0; i < files.Count / 8; i++)
            {
                ciaHeader.contentIndex[i] = 0xFF;
            }
            if (files.Count % 8 > 0)
            {
                var ind = files.Count / 8;
                for (int i = 0; i < files.Count % 8; i++)
                {
                    ciaHeader.contentIndex[ind] = (byte)((ciaHeader.contentIndex[ind] >> 1) | 0x80);
                }
            }

            //update contentCount in TMD
            tmd.header.contentCount = tmd.contentInfoRecord[0].contentChunkCount = (short)files.Count;

            //Update contentRecords
            var index = 0;

            tmd.contentChunkRecord = new List <TMD.ContentChunkRecord>();
            foreach (var f in files)
            {
                tmd.contentChunkRecord.Add(new TMD.ContentChunkRecord
                {
                    contentID    = index,
                    contentIndex = (short)index++,
                    contentType  = (short)((index == 1) ? 0 : 0x4000),
                    contentSize  = (long)f.FileSize,
                    sha256       = Kontract.Hash.SHA256.Create(f.FileData)
                });
            }

            using (var bw = new BinaryWriterX(output))
            {
                bw.BaseStream.Position = ciaHeader.headerSize;
                bw.WriteAlignment(alignement);

                //CertChain
                certChain.Write(bw.BaseStream);
                bw.WriteAlignment(alignement);

                //Ticket
                ticket.Write(bw.BaseStream);
                bw.WriteAlignment(alignement);

                //TMD
                ciaHeader.tmdSize = tmd.Write(bw.BaseStream);
                bw.WriteAlignment(alignement);

                //Actual data
                var dataOffset = bw.BaseStream.Position;
                foreach (var f in files)
                {
                    f.FileData.CopyTo(bw.BaseStream);
                }

                //CIA Header
                bw.BaseStream.Position = 0;
                ciaHeader.contentSize  = bw.BaseStream.Length - dataOffset;
                bw.WriteStruct(ciaHeader);
            }
        }
コード例 #19
0
        public void Save(Stream output)
        {
            using (var bw = new BinaryWriterX(output, ByteOrder))
            {
                Header.Block1 = (uint)((int)HeaderInfo.Version | (HeaderInfo.Unknown1 << 12) | (HeaderInfo.Unused1 << 24) | ((int)HeaderInfo.AlphaChannelFlags << 28));
                Header.Block2 = (uint)(HeaderInfo.MipMapCount | (HeaderInfo.Width << 6) | (HeaderInfo.Height << 19));
                Header.Block3 = (uint)(HeaderInfo.Unknown2 | ((int)HeaderInfo.Format << 8) | (HeaderInfo.Unknown3 << 16));
                bw.WriteStruct(Header);

                //var format = HeaderInfo.Format.ToString().StartsWith("DXT1") ? Format.DXT1 : HeaderInfo.Format.ToString().StartsWith("DXT5") ? Format.DXT5 : HeaderInfo.Format;
                Settings.Format = (HeaderInfo.Version == image_mt.Version._Switchv1) ? SwitchFormats[HeaderInfo.Format] : Formats[HeaderInfo.Format];

                if ((Format)HeaderInfo.Format == Format.DXT5_B)
                {
                    Settings.PixelShader = ToNoAlpha;
                }
                else if ((Format)HeaderInfo.Format == Format.DXT5_YCbCr)
                {
                    Settings.PixelShader = ToOptimisedColors;
                }

                List <byte[]> bitmaps = new List <byte[]>();
                foreach (var bmp in Bitmaps)
                {
                    //Set possible Swizzles
                    if (HeaderInfo.Version == image_mt.Version._3DSv1 || HeaderInfo.Version == image_mt.Version._3DSv2 || HeaderInfo.Version == image_mt.Version._3DSv3)
                    {
                        Settings.Swizzle = new CTRSwizzle(bmp.Width, bmp.Height);
                    }
                    else if (HeaderInfo.Version == image_mt.Version._Switchv1)
                    {
                        Settings.Swizzle = new SwitchSwizzle(bmp.Width, bmp.Height, Settings.Format.BitDepth, GetSwitchSwizzleFormat(Settings.Format.FormatName));    //Switch Swizzle
                    }
                    else if (Settings.Format.FormatName.Contains("DXT"))
                    {
                        Settings.Swizzle = new BlockSwizzle(bmp.Width, bmp.Height);
                    }

                    bitmaps.Add(Common.Save(bmp, Settings));
                }

                // Mipmaps, but not for Version 3DS v1
                if (HeaderInfo.Version != image_mt.Version._3DSv1)
                {
                    if (HeaderInfo.Version == image_mt.Version._Switchv1)
                    {
                        bw.Write(bitmaps.Sum(b => b.Length));
                    }
                    var offset = HeaderInfo.Version == image_mt.Version._PS3v1 ? HeaderInfo.MipMapCount * sizeof(int) + HeaderLength : 0;
                    foreach (var bitmap in bitmaps)
                    {
                        bw.Write(offset);
                        offset += bitmap.Length;
                    }
                }

                // Bitmaps
                foreach (var bitmap in bitmaps)
                {
                    bw.Write(bitmap);
                }
            }
        }
コード例 #20
0
ファイル: MES.cs プロジェクト: wabberz/Kuriimu
        public void Save(string filename)
        {
            using (BinaryWriterX bw = new BinaryWriterX(File.Create(filename)))
            {
                var textOffset = 0x40 + entries.Count() * 0x20 + sceEntries.Count() * 0x8;

                //Write texts and update textEntries
                bw.BaseStream.Position = textOffset;
                var count = 0;
                for (int i = 0; i < entries.Count(); i++)
                {
                    entries[i].nameOffset = (int)bw.BaseStream.Position;
                    entries[i].nameLength = Encoding.ASCII.GetByteCount(Labels[count].Name);
                    bw.Write(Encoding.ASCII.GetBytes(Labels[count].Name));
                    bw.WritePadding(2);
                    bw.WriteAlignment(2);

                    entries[i].stringOffset = (int)bw.BaseStream.Position;
                    entries[i].stringLength = Encoding.GetEncoding("UTF-16").GetByteCount(Labels[count].Text) / 2;
                    var modText = Labels[count++].Text.Replace("\r\n", "\x1b");
                    entries[i].stringLength += modText.Count(m => m == '\x1b');
                    bw.Write(Encoding.GetEncoding("UTF-16").GetBytes(modText));
                    bw.WritePadding(4 + modText.Count(m => m == '\x1b') * 4);
                }
                bw.WriteAlignment(4);

                //Write scenario Containers and update sceEntries
                count = 0;
                for (int i = 0; i < sceEntries.Count(); i++)
                {
                    if ((bw.BaseStream.Position & 0x4) == 0)
                    {
                        bw.WritePadding(4);
                    }
                    if (sceEntries[i].containerOffset != 0)
                    {
                        sceEntries[i].containerOffset = (int)bw.BaseStream.Position;
                        foreach (var sceTextEntry in scenarios[count++])
                        {
                            bw.Write(sceTextEntry);
                        }
                    }
                }

                //final nulls, they seem to have no reason to exist ;)
                bw.WritePadding(textOffset);

                //Write both tables
                bw.BaseStream.Position = 0x40;
                foreach (var entry in entries)
                {
                    bw.WriteStruct(entry);
                }
                foreach (var sceContainer in sceEntries)
                {
                    bw.WriteStruct(sceContainer);
                }

                //Header
                bw.BaseStream.Position = 0x0;
                bw.WriteStruct(header);
                bw.WriteStruct(entryHeader);
                bw.BaseStream.Position += 0x10;
                bw.WriteStruct(sceHeader);
                bw.Write(unk1);
            }
        }
コード例 #21
0
        public void Save(Stream input, bool leaveOpen)
        {
            using (BinaryWriterX bw = new BinaryWriterX(input, leaveOpen))
            {
                //check original sizes
                CheckOriginalSizes();

                //Write CTPK Header
                bw.WriteStruct(header);
                bw.BaseStream.Position = 0x20;

                //Write TexEntries
                foreach (var entry in entries)
                {
                    bw.WriteStruct(entry.texEntry);
                }

                //Write dataSizes
                foreach (var entry in entries)
                {
                    foreach (var size in entry.dataSizes)
                    {
                        bw.Write(size);
                    }
                }

                //Write names
                foreach (var entry in entries)
                {
                    bw.WriteASCII(entry.name + "\0");
                }

                //Write hashes
                bw.BaseStream.Position = (bw.BaseStream.Position + 0x3) & ~0x3;
                List <HashEntry> hash = entries.Select(c => c.hash).OrderBy(c => c.crc32).ToList();
                foreach (var entry in hash)
                {
                    bw.WriteStruct(entry);
                }

                //Write mipmapInfo
                foreach (var entry in entries)
                {
                    bw.WriteStruct(entry.mipmapEntry);
                }

                //Write bitmaps
                bw.BaseStream.Position = header.texSecOffset;
                var index = 0;
                foreach (var entry in entries)
                {
                    var settings = new ImageSettings
                    {
                        Width         = bmps[index].bmp.Width,
                        Height        = bmps[index].bmp.Height,
                        Format        = ImageSettings.ConvertFormat(entry.texEntry.imageFormat),
                        PadToPowerOf2 = false
                    };
                    bw.Write(Common.Save(bmps[index++].bmp, settings));

                    if (entry.texEntry.mipLvl > 1)
                    {
                        for (int i = 1; i < entry.texEntry.mipLvl; i++)
                        {
                            settings = new ImageSettings
                            {
                                Width             = bmps[index].bmp.Width << i,
                                    Height        = bmps[index].bmp.Height << i,
                                    Format        = ImageSettings.ConvertFormat(entry.mipmapEntry.mipmapFormat),
                                    PadToPowerOf2 = false
                            };
                            bw.Write(Common.Save(bmps[index++].bmp, settings));
                        }
                    }
                }
            }
        }
コード例 #22
0
        public void Save(string filename)
        {
            var ascii = Encoding.ASCII;
            var utf16 = Encoding.Unicode;

            var texts = new List <byte[]>();
            var names = new List <byte[]>();

            foreach (var label in Labels)
            {
                texts.Add(utf16.GetBytes(label.Text + "\0"));
                names.Add(ascii.GetBytes(label.Name + "\0"));
            }

            var papaHeaderSize  = 0x8;
            var entryHeaderSize = 0x14;
            var entryCount      = Labels.Count;

            using (BinaryWriterX bw = new BinaryWriterX(File.Create(filename)))
            {
                //PAPA Header
                bw.WriteASCII("PAPA\0\0\0\0");

                //Offset list
                var offsetHeader = new OffsetHeader();
                offsetHeader.entryCount = entryCount + 1;
                offsetHeader.dataSize   = (entryCount + 1) * sizeof(int) + papaHeaderSize;
                bw.WriteStruct(offsetHeader);

                //Offsets
                var initOff = offsetHeader.headerSize + offsetHeader.dataSize;
                for (int i = 0; i < entryCount; i++)
                {
                    bw.Write(initOff);
                    initOff += entryHeaderSize + 4 + texts[i].Length;
                    initOff  = (initOff + 3) & ~3;
                    initOff += names[i].Length;
                    initOff  = (initOff + 3) & ~3;
                }
                bw.Write(initOff);

                //Entries
                for (int i = 0; i < entryCount; i++)
                {
                    var entryDataSize = (((entryHeaderSize + 4 + texts[i].Length + 3) & ~3) + names[i].Length + 3) & ~3;

                    bw.Write(entryDataSize);
                    bw.Write(3);
                    bw.Write(0x14);
                    bw.Write(0x18);
                    bw.Write((entryHeaderSize + 4 + texts[i].Length + 3) & ~3);

                    bw.WriteASCII("Msg\0");
                    bw.Write(texts[i]);
                    bw.WriteAlignment(4);
                    bw.Write(names[i]);
                    bw.WriteAlignment(4);
                }

                //End Mark Entry
                bw.Write(0);
                bw.Write(0);
            }
        }
コード例 #23
0
        public void Save(Stream xfsa)
        {
            //Update FileInfo
            int offset = 0;

            foreach (var file in Files)
            {
                entries[file.dirEntry.fileEntryOffset + file.fileCountInDir].offset = offset >> 4;
                file.fileEntry.offset = offset >> 4;

                entries[file.dirEntry.fileEntryOffset + file.fileCountInDir].size = (int)file.FileSize;
                file.fileEntry.size = (int)file.FileSize;

                var newOffset = ((offset + file.FileSize) % 16 == 0) ? offset + file.FileSize + 16 : (offset + file.FileSize + 0xf) & ~0xf;
                offset = (int)newOffset;
            }

            using (var bw = new BinaryWriterX(xfsa))
            {
                //Table 0
                bw.BaseStream.Position  = 0x24;
                header.table0Offset     = (int)bw.BaseStream.Position;
                header.table0EntryCount = (short)table0.Count;
                bw.Write(CompressTable(table0, table0Comp));

                //Table 1
                bw.BaseStream.Position  = (bw.BaseStream.Position + 3) & ~3;
                header.table1Offset     = (int)bw.BaseStream.Position;
                header.table1EntryCount = (short)table1.Count;
                bw.Write(CompressTable(table1, table1Comp));

                //FileEntries
                bw.BaseStream.Position      = (bw.BaseStream.Position + 3) & ~3;
                header.fileEntryTableOffset = (int)bw.BaseStream.Position;
                header.fileEntryCount       = entries.Count;
                bw.Write(CompressTable(entries, entriesComp));

                //StringTable
                bw.BaseStream.Position = (bw.BaseStream.Position + 3) & ~3;
                header.nameTableOffset = (int)bw.BaseStream.Position;
                bw.Write(Level5.Compress(new MemoryStream(stringTable), stringComp));

                //FileData
                bw.BaseStream.Position = (bw.BaseStream.Position + 0xf) & ~0xf;
                header.dataOffset      = (int)bw.BaseStream.Position;
                foreach (var file in Files)
                {
                    bw.BaseStream.Position = header.dataOffset + (file.fileEntry.offset << 4);
                    file.FileData.CopyTo(bw.BaseStream);
                    if (bw.BaseStream.Position % 16 == 0)
                    {
                        bw.WritePadding(16);
                    }
                    else
                    {
                        bw.WriteAlignment(16);
                    }
                }

                //Header
                bw.BaseStream.Position = 0;
                bw.WriteStruct(header);
            }

            //Table 1

            /*var ms = new MemoryStream();
             * new BinaryWriterX(ms, true).WriteMultiple(table0);
             * ms.Position = 0;
             * var newTable1 = Level5.Compress(ms, (Level5.Method)table1Comp);
             *
             * //Table 2
             * ms = new MemoryStream();
             * new BinaryWriterX(ms, true).WriteMultiple(table1);
             * ms.Position = 0;
             * var newTable2 = Level5.Compress(ms, (Level5.Method)table2Comp);
             *
             * //Update Entries
             * Files = Files.OrderBy(f => f.entry.entry.comb1 & 0x01ffffff).ToList();
             * int offset = 0;
             * foreach (var file in Files) offset = file.UpdateEntry(offset);
             *
             * //Get compressed Entry section
             * Files = Files.OrderBy(f => f.entry.ID).ToList();
             * ms = new MemoryStream();
             * new BinaryWriterX(ms, true).WriteMultiple(Files.Select(f => f.entry.entry));
             * ms.Position = 0;
             * var newEntryTable = Level5.Compress(ms, (Level5.Method)entriesComp);
             *
             * //Update header
             * header.nameTableOffset = (uint)(0x24 + ((newTable1.Length + 3) & ~3) + ((newTable2.Length + 3) & ~3) + ((newEntryTable.Length + 3) & ~3));
             * header.dataOffset = (uint)(((header.nameTableOffset + nameC.Length) + 0xf) & ~0xf);
             *
             * using (BinaryWriterX bw = new BinaryWriterX(xfsa))
             * {
             *  //Header
             *  bw.WriteStruct(header);
             *
             *  //Table 1
             *  bw.Write(newTable1);
             *  bw.WriteAlignment(4);
             *
             *  //Table 2
             *  bw.Write(newTable2);
             *  bw.WriteAlignment(4);
             *
             *  //Entries
             *  bw.Write(newEntryTable);
             *  bw.WriteAlignment(4);
             *
             *  //Names
             *  bw.Write(nameC);
             *  bw.WriteAlignment();
             *
             *  //Files
             *  Files = Files.OrderBy(f => f.entry.entry.comb1 & 0x01ffffff).ToList();
             *  foreach (var file in Files)
             *  {
             *      file.FileData.CopyTo(bw.BaseStream);
             *      if (bw.BaseStream.Position % 0x10 != 0)
             *          bw.WriteAlignment();
             *      else
             *      {
             *          bw.Write(new byte[0x10]);
             *      }
             *  }
             *
             *
             *  //FileEntries Table
             *  //bw.Write((entries.Count * 0xc) << 3);
             *
             *  /*uint offset = 0;
             *  List<XFSAFileInfo> files = new List<XFSAFileInfo>();
             *  foreach (var entry in entries)
             *  {
             *      var file = Files.Find(c => c.entry.comb1 == entry.comb1);
             *      files.Add(file);
             *
             *      //catch file limits
             *      if (file.FileData.Length >= 0x100000)
             *      {
             *          throw new Exception("File " + file.FileName + " is too big to pack into this archive type!");
             *      }
             *      else if (offset + dataOffset >= 0x20000000)
             *      {
             *          throw new Exception("The archive can't be bigger than 0x10000000 Bytes.");
             *      }
             *
             *      //edit entry
             *      entry.comb1 = (entry.comb1 & 0xfe000000) | (offset >> 4);
             *      entry.comb2 = (entry.comb1 & 0xfff00000) | ((uint)file.FileData.Length);
             *
             *      //write entry
             *      bw.WriteStruct(entry);
             *
             *      //edit values
             *      offset = (uint)(((offset + file.FileData.Length) + 0xf) & ~0xf);
             *  }*/

            //Nametable
            //bw.Write(nameC);

            //Files
            //bw.BaseStream.Position = dataOffset;
            //foreach (var file in files)
            //{
            //    file.FileData.CopyTo(bw.BaseStream);
            //    bw.BaseStream.Position = (bw.BaseStream.Position + 0xf) & ~0xf;
            //}

            //Header
            //header.nameTableOffset = (uint)(0x24 + table1.Length + table2.Length + entries.Count * 0xc + 4);
            //header.dataOffset = (uint)dataOffset;
            //bw.BaseStream.Position = 0;
            //bw.WriteStruct(header);
            //}
        }
コード例 #24
0
        public void Save(Stream output)
        {
            using (var bw = new BinaryWriterX(output))
            {
                // Header
                bw.Write(Magic);
                bw.Write(Count);
                bw.Write(nIDOffset);
                bw.Write(Unk1);
                bw.Write(nIDStringOffset);
                bw.Write(pstrBgmNameOffset);
                bw.Write(pstrArtistNameOffset);
                bw.Write(pstrFileNameOffset);
                bw.Write(nOrderOffset);
                bw.Write(nMixOffset);
                bw.Write(pstrRcidOffset);
                bw.Write(Unk2);
                bw.Write(Unk3);
                bw.WritePadding(0x10, 0x77);

                // Constant Strings
                bw.BaseStream.Position = nIDStringOffset;
                bw.WriteASCII(nIDString);
                bw.Write((byte)0);
                bw.WriteASCII(pstrBgmNameString);
                bw.Write((byte)0);
                bw.WriteASCII(pstrArtistNameString);
                bw.Write((byte)0);
                bw.WriteASCII(pstrFileNameString);
                bw.Write((byte)0);
                bw.WriteASCII(nOrderString);
                bw.Write((byte)0);
                bw.WriteASCII(nMixString);
                bw.Write((byte)0);
                bw.WriteASCII(pstrRcidString);
                bw.Write((byte)0);

                // BgmName
                Data.pstrBgmNameOffset = (int)bw.BaseStream.Position;
                bw.WriteASCII(BgmName);
                bw.Write((byte)0);

                // ArtistName
                Data.pstrArtistNameOffset = (int)bw.BaseStream.Position;
                bw.WriteASCII(ArtistName);
                bw.Write((byte)0);

                // FileName
                Data.pstrFileNameOffset = (int)bw.BaseStream.Position;
                bw.WriteASCII(FileName);
                bw.Write((byte)0);

                // Rcid
                Data.pstrRcidOffset = (int)bw.BaseStream.Position;
                bw.WriteASCII(Rcid);
                bw.Write((byte)0);

                // Data
                bw.BaseStream.Position = nIDOffset;
                Data.nID -= 1;
                bw.WriteStruct(Data);
                bw.WritePadding(0x4, 0x77);
            }
        }