Пример #1
0
 /// <summary>
 /// Load BNSA Shared method
 /// </summary>
 /// <param name="memory">BSNA Memory to load</param>
 private void LoadBNSA(byte[] memory)
 {
     ActiveBNSA = new BNSAFile(memory);
     ActiveBNSA.ResolveReferences();
     ActiveBNSA.CreateWorkingPalettes();
     animationIndexUpDown.Maximum = ActiveBNSA.Animations.Count - 1;
     paletteIndexUpDown.Maximum   = ActiveBNSA.WorkingPalettes.Count - 1;
     animationCountLabel.Content  = "of " + animationIndexUpDown.Maximum;
     paletteCountLabel.Content    = "of " + (ActiveBNSA.WorkingPalettes.Count - 1);
     //frameIndexUpDown.Maximum = ActiveBNSA.Animations[0].Frames.Count - 1;
     ChangeAnimation();
 }
        /// <summary>
        /// Unpacks a BNSA file into parts.
        /// </summary>
        /// <param name="bnsaFile">Path to a BNSA file</param>
        /// <param name="outputFolder">Directory to output files to. Will be created if it does not exist.</param>
        private static void unpackBNSA(string bnsaFile, string outputFolder)
        {
            BNSAFile bnsa = new BNSAFile(bnsaFile);

            bnsa.ResolveReferences();
            bnsa.Unpack(outputFolder);
            bnsa.GenerateLinkingXML(outputFolder);
            if (true)
            {
                endProgram("Testing done...", 0);
            }
            //TODO: Check if archive is compressed. Likely will not be, but you never know. Can be identified by first 4 bytes.
            writeVerboseMessage("Unpacking " + bnsaFile + " to " + outputFolder);
            //Extract/Unpack
            byte[] inputFileBytes = File.ReadAllBytes(bnsaFile);
            int    currentOffset  = 4;

            List <byte[]> archiveParts = new List <byte[]>();

            //Animation pointers
            writeVerboseMessage("Reading Animation Pointers");
            int animPointersLength = inputFileBytes[3] * 4;

            byte[] animPointers = new byte[animPointersLength];
            Array.Copy(inputFileBytes, currentOffset, animPointers, 0, animPointersLength);
            currentOffset += animPointersLength;

            //Frame data
            writeVerboseMessage("Calculating Frames data");
            int frameDataLength = findFrameDataEnd(inputFileBytes, currentOffset) - currentOffset;

            byte[] frameData = new byte[frameDataLength];
            Array.Copy(inputFileBytes, currentOffset, frameData, 0, frameDataLength);
            currentOffset += frameDataLength;

            //Tileset data
            writeVerboseMessage("Calculating Tilesets data");
            int tilesetDataLength = findTilesetDataEnd(inputFileBytes, currentOffset) - currentOffset;

            byte[] tilesetData = new byte[tilesetDataLength];
            Array.Copy(inputFileBytes, currentOffset, tilesetData, 0, tilesetDataLength);
            List <int>    tilesetOffsetList = getTilesetOffsetList(tilesetData, currentOffset - 4);
            List <byte[]> tilesetsList      = splitTilesets(tilesetData);

            currentOffset += tilesetDataLength;

            //Palette data
            writeVerboseMessage("Calculating Palettes data");
            int paletteDataLength = findPaletteDataEnd(inputFileBytes, currentOffset) - currentOffset;

            byte[] paletteData = new byte[paletteDataLength];
            Array.Copy(inputFileBytes, currentOffset, paletteData, 0, paletteDataLength);
            List <int>    paletteOffsetList = getPaletteOffsetList(paletteData, currentOffset + 4);
            List <byte[]> paletteList       = splitPalettes(paletteData);

            currentOffset += paletteDataLength;

            //Mini-Animations data
            writeVerboseMessage("Calculating Mini Animations data");
            int miniAnimDataLength = findMiniAnimDataEnd(inputFileBytes, currentOffset) - currentOffset;

            byte[] miniAnimData = new byte[miniAnimDataLength];
            Array.Copy(inputFileBytes, currentOffset, miniAnimData, 0, miniAnimDataLength);
            List <int>    miniAnimDataOffsetList = getMiniAnimOffsetList(miniAnimData, currentOffset);
            List <byte[]> miniAnimsList          = splitMiniAnims(miniAnimData);

            currentOffset += miniAnimDataLength;

            //Object list data
            writeVerboseMessage("Calculating Objects Lists data");
            int objectListDataLength = findObjectListDataEnd(inputFileBytes, currentOffset) - currentOffset;

            byte[] objectListData = new byte[objectListDataLength];
            Array.Copy(inputFileBytes, currentOffset, objectListData, 0, objectListDataLength);
            List <int>    objectListOffsetList = getObjectListOffsetList(objectListData, currentOffset);
            List <byte[]> objectListsList      = splitObjectLists(objectListData);

            currentOffset += objectListDataLength;



            //XML document for animation frames format
            //XmlDocument frameDoc = new XmlDocument();
            //XmlNode animNode = frameDoc.CreateElement("animation");
            //frameDoc.AppendChild(animNode);

            //XmlNode frameNode = frameDoc.CreateElement("frame");
            //XmlAttribute tilesetAttr = frameDoc.CreateAttribute("tileset");
            //tilesetAttr.Value = tilesetsList[0].ToString();
            //frameNode.Attributes.Append(tilesetAttr);
            //animNode.AppendChild(frameNode);

            //frameDoc.Save()



            //Add arrays to list for export
            archiveParts.Add(animPointers);
            archiveParts.Add(frameData);
            archiveParts.Add(tilesetData);
            archiveParts.Add(paletteData);
            archiveParts.Add(miniAnimData);
            archiveParts.Add(objectListData);

            //create directories and save
            writeVerboseMessage("Creating output directories");
            string framesPath      = outputFolder + @"\\frames";
            string tilesetsPath    = outputFolder + @"\\tilesets";
            string palettesPath    = outputFolder + @"\\palettes";
            string miniAnimsPath   = outputFolder + @"\\minianims";
            string objectListsPath = outputFolder + @"\\objectlists";

            Directory.CreateDirectory(outputFolder);
            Directory.CreateDirectory(framesPath);
            Directory.CreateDirectory(tilesetsPath);
            Directory.CreateDirectory(palettesPath);
            Directory.CreateDirectory(miniAnimsPath);
            Directory.CreateDirectory(objectListsPath);

            //raw parts export
            writeVerboseMessage("Extracting raw parts");
            File.WriteAllBytes(framesPath + "\\frames.bin", archiveParts[1].ToArray());
            File.WriteAllBytes(tilesetsPath + "\\tilesets.bin", archiveParts[2].ToArray());
            File.WriteAllBytes(palettesPath + "\\palettes.bin", archiveParts[3].ToArray());
            File.WriteAllBytes(miniAnimsPath + "\\minianims.bin", archiveParts[4].ToArray());
            File.WriteAllBytes(objectListsPath + "\\objectlists.bin", archiveParts[5].ToArray());


            //export tiles
            for (int i = 0; i < tilesetsList.Count; i++)
            {
                writeVerboseMessage("Extracting Tileset " + i);
                File.WriteAllBytes(tilesetsPath + "\\tiles" + i + ".bin", tilesetsList[i]);
            }

            //export palettes
            for (int i = 0; i < paletteList.Count; i++)
            {
                writeVerboseMessage("Extracting Palette " + i);
                File.WriteAllBytes(palettesPath + "\\palette" + i + ".bin", paletteList[i]);
            }

            //export minianims
            for (int i = 0; i < miniAnimsList.Count; i++)
            {
                writeVerboseMessage("Extracting Mini Animation " + i);
                File.WriteAllBytes(miniAnimsPath + "\\minianim" + i + ".bin", miniAnimsList[i]);
            }

            //export objectlists
            for (int i = 0; i < objectListsList.Count; i++)
            {
                writeVerboseMessage("Extracting Object List " + i);
                File.WriteAllBytes(objectListsPath + "\\objectlists" + i + ".bin", objectListsList[i]);
            }


            writeVerboseMessage("Creating BNSA Project file...");

            XmlWriterSettings settings = new XmlWriterSettings {
                Indent = true
            };

            using (XmlWriter writer = XmlWriter.Create(framesPath + "\\animations.xml", settings))
            {
                writer.WriteStartDocument();
                writer.WriteStartElement("animation");

                for (int i = 0; i < frameData.Count(); i++)
                {
                    writer.WriteStartElement("frame" + i.ToString());
                    //writer.WriteElementString("tileset", getMatchingTileset(frameData, tilesetOffsetList, i));
                    writer.WriteElementString("tileset", "tileset0.bin");
                    writer.WriteElementString("palette", "palette0.bin");
                    writer.WriteElementString("minianim", "minianim0.bin");
                    writer.WriteElementString("objectlist", "objectlist0.bin");
                    writer.WriteElementString("delay", 1.ToString());
                    writer.WriteElementString("flags", "loop");

                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
                writer.WriteEndDocument();
            }


            XDocument xDoc = new XDocument(new XDeclaration("1.0", "UTF-16", null));

            for (int i = 0; i < frameData.Count(); i++)
            {
                //writer.WriteStartElement("frame" + i.ToString());
                ////writer.WriteElementString("tileset", getMatchingTileset(frameData, tilesetOffsetList, i));
                //writer.WriteElementString("tileset", "tileset0.bin");
                //writer.WriteElementString("palette", "palette0.bin");
                //writer.WriteElementString("minianim", "minianim0.bin");
                //writer.WriteElementString("objectlist", "objectlist0.bin");
                //writer.WriteElementString("delay", 1.ToString());
                //writer.WriteElementString("flags", "loop");

                //new XElement("Frame",
                //    new XElement("tileset",
                //        new XComment("Only 3 elements for demo purposes"),
                //        new XElement("EmpId", "5"),
                //        new XElement("Name", "Kimmy"),
                //        new XElement("Sex", "Female"),
                //        new XAttribute("index", i);
                //        )));
            }



            StringWriter sw = new StringWriter();

            xDoc.Save(sw);
            Console.WriteLine(sw);



            //frameDoc.Save(framesPath + "\\animations.xml");

            endProgram("Sprite unpacked into " + outputFolder, 0);
        }