Ejemplo n.º 1
0
 public static SarcData SetSarcFiles(this Dictionary <string, byte[]> dict, SarcData data)
 {
     data.Files = dict;
     return(data);
 }
Ejemplo n.º 2
0
 public static Tuple <int, byte[]> PackSarcData(this SarcData data)
 {
     return(SARC.PackN(data));
 }
Ejemplo n.º 3
0
 public static Dictionary <string, byte[]> GetSarcFiles(this SarcData sarcData)
 {
     return(sarcData.Files);
 }
Ejemplo n.º 4
0
 public static byte[] Compress(this SarcData data)
 {
     return(YAZ0.Compress(data.PackSarc()));
 }
Ejemplo n.º 5
0
 public static byte[] PackSarc(this SarcData data)
 {
     return(data.PackSarcData().GetBytes());
 }
Ejemplo n.º 6
0
        private void PatchButtonClick(object sender, EventArgs e)
        {
            if (CommonSzs == null || targetPatch == null)
            {
                MessageBox.Show("Open a valid SZS first");
                return;
            }
            if (tbImageFile.Text.Trim() == "")
            {
                if (LayoutPatchList.SelectedIndex <= 0)
                {
                    MessageBox.Show("There is nothing to patch");
                    return;
                }
                if (MessageBox.Show("Are you sure you want to continue without selecting a background?", "", MessageBoxButtons.YesNo) == DialogResult.No)
                {
                    return;
                }
            }
            else if (!File.Exists(tbImageFile.Text))
            {
                MessageBox.Show($"{tbImageFile.Text} not found!");
                return;
            }

            SaveFileDialog sav = new SaveFileDialog()
            {
                Filter   = "SZS file|*.szs",
                FileName = targetPatch.szsName
            };

            if (sav.ShowDialog() != DialogResult.OK)
            {
                return;
            }

            SzsPatcher Patcher = new SzsPatcher(CommonSzs, Templates);

            var res = BflytFile.PatchResult.OK;

            if (tbImageFile.Text.Trim() != "")
            {
                if (!BgImageCheck(true))
                {
                    return;
                }

                res = Patcher.PatchMainBG(File.ReadAllBytes(tbImageFile.Text));
                if (res == BflytFile.PatchResult.Fail)
                {
                    MessageBox.Show("Couldn't patch this file, it might have been already modified or it's from an unsupported system version.");
                    return;
                }
                else if (res == BflytFile.PatchResult.CorruptedFile)
                {
                    MessageBox.Show("This file has been already patched with another tool and is not compatible, you should get an unmodified layout.");
                    return;
                }
            }

            if (LayoutPatchList.SelectedIndex != 0)
            {
                Patcher.EnableAnimations = !UseAnim.Checked;
                var layoutres = Patcher.PatchLayouts(LayoutPatchList.SelectedItem as LayoutPatch, targetPatch.NXThemeName, targetPatch.NXThemeName == "home");
                if (layoutres == BflytFile.PatchResult.Fail)
                {
                    MessageBox.Show("One of the target files for the selected layout patch is missing in the SZS, you are probably using an already patched SZS");
                    return;
                }
                else if (layoutres == BflytFile.PatchResult.CorruptedFile)
                {
                    MessageBox.Show("A layout in this SZS is missing a pane required for the selected layout patch, you are probably using an already patched SZS");
                    return;
                }
                layoutres = Patcher.PatchAnimations((LayoutPatchList.SelectedItem as LayoutPatch).Anims);
                if (layoutres != BflytFile.PatchResult.OK)
                {
                    MessageBox.Show("Error while patching the animations!");
                    return;
                }
            }

            if (targetPatch.NXThemeName == "home")
            {
                foreach (var n in TextureReplacement.NxNameToList[targetPatch.NXThemeName])
                {
                    if (HomeAppletIcons[n.NxThemeName] == null)
                    {
                        continue;
                    }
                    string path = HomeAppletIcons[n.NxThemeName];
                    if (!path.EndsWith(".dds") && !IcontoDDS(ref path))
                    {
                        return;
                    }
                    HomeAppletIcons[n.NxThemeName] = path;
                    Patcher.PatchAppletIcon(File.ReadAllBytes(path), n.NxThemeName);
                }
            }
            else if (targetPatch.NXThemeName == "lock" && LockCustomIcon != null)
            {
                if (!LockCustomIcon.EndsWith(".dds") && !IcontoDDS(ref LockCustomIcon))
                {
                    return;
                }
                Patcher.PatchAppletIcon(File.ReadAllBytes(LockCustomIcon), TextureReplacement.Entrance[0].NxThemeName);
            }

            CommonSzs = Patcher.GetFinalSarc();
            var sarc = SARC.PackN(CommonSzs);

            File.WriteAllBytes(sav.FileName, ManagedYaz0.Compress(sarc.Item2, 3, (int)sarc.Item1));
            GC.Collect();

            if (res == BflytFile.PatchResult.AlreadyPatched)
            {
                MessageBox.Show("Done, This file has already been patched before.\r\nIf you have issues try with an unmodified file");
            }
            else
            {
                MessageBox.Show("Done");
            }
        }
Ejemplo n.º 7
0
        private void PatchButtonClick(object sender, EventArgs e)
        {
            if (CommonSzs == null || targetPatch == null)
            {
                MessageBox.Show("Open a valid SZS first");
                return;
            }
            if (tbImageFile.Text.Trim() == "")
            {
                if (LayoutPatchList.SelectedIndex <= 0)
                {
                    MessageBox.Show("There is nothing to patch");
                    return;
                }

                if (MessageBox.Show("Are you sure you want to continue without selecting a background image ?", "", MessageBoxButtons.YesNo) == DialogResult.No)
                {
                    return;
                }
            }
            else if (!File.Exists(tbImageFile.Text))
            {
                MessageBox.Show($"{tbImageFile.Text} not found!");
                return;
            }

            SaveFileDialog sav = new SaveFileDialog()
            {
                Filter   = "SZS file|*.szs",
                FileName = targetPatch.szsName
            };

            if (sav.ShowDialog() != DialogResult.OK)
            {
                return;
            }

            SzsPatcher Patcher = new SzsPatcher(CommonSzs, Templates);

            var res = true;

            if (tbImageFile.Text.Trim() != "")
            {
                if (!BgImageCheck(true))
                {
                    return;
                }

                res = Patcher.PatchMainBG(File.ReadAllBytes(tbImageFile.Text));
                if (!res)
                {
                    MessageBox.Show("Couldn't patch this file, it might have been already modified or it's from an unsupported system version.");
                    return;
                }
            }

            if (targetPatch.NXThemeName == "home")
            {
                foreach (var n in TextureReplacement.NxNameToList[targetPatch.NXThemeName])
                {
                    if (HomeAppletIcons[n.NxThemeName] == null)
                    {
                        continue;
                    }
                    string path = HomeAppletIcons[n.NxThemeName];
                    if (!path.EndsWith(".dds") && !IcontoDDS(ref path))
                    {
                        return;
                    }
                    HomeAppletIcons[n.NxThemeName] = path;
                    if (!Patcher.PatchAppletIcon(File.ReadAllBytes(path), n.NxThemeName))
                    {
                        MessageBox.Show($"Failed applet icon patch for {n.NxThemeName}");
                        return;
                    }
                }
            }
            else if (targetPatch.NXThemeName == "lock" && LockCustomIcon != null)
            {
                if (!LockCustomIcon.EndsWith(".dds") && !IcontoDDS(ref LockCustomIcon))
                {
                    return;
                }
                Patcher.PatchAppletIcon(File.ReadAllBytes(LockCustomIcon), TextureReplacement.Entrance[0].NxThemeName);
            }

            if (LayoutPatchList.SelectedIndex != 0)
            {
                Patcher.EnableAnimations = !UseAnim.Checked;
                var layoutres = Patcher.PatchLayouts(LayoutPatchList.SelectedItem as LayoutPatch, targetPatch.NXThemeName, targetPatch);
                if (!layoutres)
                {
                    MessageBox.Show("One of the target files for the selected layout patch is missing in the SZS, you are probably using an already patched SZS");
                    return;
                }
                layoutres = Patcher.PatchAnimations((LayoutPatchList.SelectedItem as LayoutPatch).Anims);
                if (!layoutres)
                {
                    MessageBox.Show("Error while patching the animations !");
                    return;
                }
            }

            CommonSzs = Patcher.GetFinalSarc();
            var sarc = SARC.PackN(CommonSzs);

            File.WriteAllBytes(sav.FileName, ManagedYaz0.Compress(sarc.Item2, 3, (int)sarc.Item1));
            GC.Collect();

            if (Patcher.PatchTemplate.RequiresCodePatch)
            {
                MessageBox.Show("The file has been patched successfully but due to memory limitations this szs requires an extra code patch to be applied to the home menu, if you use NXThemesInstaller to install this it will be done automatically, otherwise you need to manually copy the patches from https://github.com/exelix11/SwitchThemeInjector/tree/master/SwitchThemesNX/romfs to the exefs patches directory of your cfw");
            }
            else
            {
                MessageBox.Show("Done");
            }
        }
Ejemplo n.º 8
0
        public static (LayoutPatch, string) Diff(SarcData original, SarcData edited)
        {
            List <LayoutFilePatch> Patches = new List <LayoutFilePatch>();

            if (!ScrambledEquals <string>(original.Files.Keys, edited.Files.Keys))
            {
                throw new Exception("The provided archives don't have the same files");
            }

            bool hasAtLeastAnExtraGroup = false;             //Used to detect if animations are properly implemented

            foreach (var f in original.Files.Keys.Where(x => x.EndsWith(".bflyt")))
            {
                if (original.Files[f].SequenceEqual(edited.Files[f]))
                {
                    continue;
                }
                BflytFile _or = new BflytFile(original.Files[f]);
                BflytFile _ed = new BflytFile(edited.Files[f]);

                List <PanePatch> curFile = new List <PanePatch>();
                foreach (var orpane_ in _or.EnumeratePanes().Where(x => x is INamedPane))
                {
                    var edpane = _ed[((INamedPane)orpane_).PaneName];
                    if (edpane == null)
                    {
                        throw new Exception($"{f} is missing {((INamedPane)orpane_).PaneName}");
                    }
                    if (orpane_.name != edpane.name)
                    {
                        throw new Exception($"{f} : {((INamedPane)orpane_).PaneName} Two panes with the same name are of a different type");
                    }
                    if (IgnorePaneList.Contains(orpane_.name))
                    {
                        continue;
                    }

                    var edPan = (Pan1Pane)edpane;
                    var orPan = (Pan1Pane)orpane_;

                    PanePatch curPatch = new PanePatch()
                    {
                        PaneName = edPan.PaneName
                    };
                    curPatch.UsdPatches = MakeUsdPatch(edPan.UserData, orPan.UserData);
                    if (edPan.data.SequenceEqual(orPan.data))
                    {
                        if (curPatch.UsdPatches != null)
                        {
                            curFile.Add(curPatch);
                        }
                        continue;
                    }

                    if (!VecEqual(edPan.Position, orPan.Position))
                    {
                        curPatch.Position = ToNullVec(edPan.Position);
                    }
                    if (!VecEqual(edPan.Rotation, orPan.Rotation))
                    {
                        curPatch.Rotation = ToNullVec(edPan.Rotation);
                    }
                    if (!VecEqual(edPan.Scale, orPan.Scale))
                    {
                        curPatch.Scale = ToNullVec(edPan.Scale);
                    }
                    if (!VecEqual(edPan.Size, orPan.Size))
                    {
                        curPatch.Size = ToNullVec(edPan.Size);
                    }
                    if (edPan.Visible != orPan.Visible)
                    {
                        curPatch.Visible = edPan.Visible;
                    }

                    if (edPan.originX != orPan.originX)
                    {
                        curPatch.OriginX = (byte)edPan.originX;
                    }
                    if (edPan.originY != orPan.originY)
                    {
                        curPatch.OriginY = (byte)edPan.originY;
                    }
                    if (edPan.ParentOriginX != orPan.ParentOriginX)
                    {
                        curPatch.ParentOriginX = (byte)edPan.ParentOriginX;
                    }
                    if (edPan.ParentOriginY != orPan.ParentOriginY)
                    {
                        curPatch.ParentOriginY = (byte)edPan.ParentOriginY;
                    }

                    if (edPan is Pic1Pane && orPan is Pic1Pane)
                    {
                        var edPic = (Pic1Pane)edPan;
                        var orPic = (Pic1Pane)orPan;
                        if (edPic.ColorTopLeft != orPic.ColorTopLeft)
                        {
                            curPatch.PaneSpecific0 = edPic.ColorTopLeft.AsHexLEString();
                        }
                        if (edPic.ColorTopRight != orPic.ColorTopRight)
                        {
                            curPatch.PaneSpecific1 = edPic.ColorTopRight.AsHexLEString();
                        }
                        if (edPic.ColorBottomLeft != orPic.ColorBottomLeft)
                        {
                            curPatch.PaneSpecific2 = edPic.ColorBottomLeft.AsHexLEString();
                        }
                        if (edPic.ColorBottomRight != orPic.ColorBottomRight)
                        {
                            curPatch.PaneSpecific3 = edPic.ColorBottomRight.AsHexLEString();
                        }
                    }

                    if (edPan is Txt1Pane && orPan is Txt1Pane)
                    {
                        var edTxt = (Txt1Pane)edPan;
                        var orTxt = (Txt1Pane)orPan;
                        if (edTxt.FontTopColor != orTxt.FontTopColor)
                        {
                            curPatch.PaneSpecific0 = edTxt.FontTopColor.AsHexLEString();
                        }
                        if (edTxt.ShadowTopColor != orTxt.ShadowTopColor)
                        {
                            curPatch.PaneSpecific1 = edTxt.ShadowTopColor.AsHexLEString();
                        }
                        if (edTxt.FontBottomColor != orTxt.FontBottomColor)
                        {
                            curPatch.PaneSpecific2 = edTxt.FontBottomColor.AsHexLEString();
                        }
                        if (edTxt.ShadowBottomColor != orTxt.ShadowBottomColor)
                        {
                            curPatch.PaneSpecific3 = edTxt.ShadowBottomColor.AsHexLEString();
                        }
                    }
                    curFile.Add(curPatch);
                }

                List <ExtraGroup> extraGroups = new List <ExtraGroup>();
                string[]          ogPanes     = _or.EnumeratePanes(_or.RootGroup).Select(x => ((Grp1Pane)x).GroupName).ToArray();
                var edPanes = _ed.EnumeratePanes(_ed.RootGroup).Cast <Grp1Pane>();
                foreach (var p in edPanes)
                {
                    if (ogPanes.Contains(p.GroupName))
                    {
                        continue;
                    }
                    extraGroups.Add(new ExtraGroup()
                    {
                        GroupName = p.GroupName, Panes = p.Panes.ToArray()
                    });
                    hasAtLeastAnExtraGroup = true;
                }
                if (extraGroups.Count == 0)
                {
                    extraGroups = null;
                }

                List <MaterialPatch> materials = new List <MaterialPatch>();
                if (_ed.GetMat != null && _or.GetMat != null)
                {
                    var edMat = _ed.GetMat;
                    foreach (var orM in _or.GetMat.Materials)
                    {
                        var edM = edMat.Materials.Where(x => x.Name == orM.Name).FirstOrDefault();
                        if (edM == null)
                        {
                            continue;
                        }
                        if (edM.ForegroundColor == orM.ForegroundColor && edM.BackgroundColor == orM.BackgroundColor)
                        {
                            continue;
                        }
                        MaterialPatch m = new MaterialPatch()
                        {
                            MaterialName = orM.Name
                        };
                        if (edM.ForegroundColor != orM.ForegroundColor)
                        {
                            m.ForegroundColor = edM.ForegroundColor.AsHexLEString();
                        }
                        if (edM.BackgroundColor != orM.BackgroundColor)
                        {
                            m.BackgroundColor = edM.BackgroundColor.AsHexLEString();
                        }
                        materials.Add(m);
                    }
                }
                if (materials.Count == 0)
                {
                    materials = null;
                }

                if (curFile.Count > 0 || extraGroups?.Count > 0 || materials?.Count > 0)
                {
                    Patches.Add(new LayoutFilePatch()
                    {
                        FileName = f, Patches = curFile.ToArray(), Materials = materials?.ToArray(), AddGroups = extraGroups?.ToArray()
                    });
                }
            }
            if (Patches.Count == 0)             //animation edits depend on bflyt changes so this is relevant
            {
                throw new Exception("Couldn't find any difference");
            }

            string Message = null;

            List <AnimFilePatch> AnimPatches = new List <AnimFilePatch>();

            foreach (var f in original.Files.Keys.Where(x => x.EndsWith(".bflan")))
            {
                if (original.Files[f].SequenceEqual(edited.Files[f]))
                {
                    continue;
                }
                BflanFile anim = new BflanFile(edited.Files[f]);
                AnimPatches.Add(new AnimFilePatch()
                {
                    FileName = f, AnimJson = BflanSerializer.ToJson(anim)
                });
            }
            if (AnimPatches.Count == 0)
            {
                AnimPatches = null;
            }
            else if (!hasAtLeastAnExtraGroup)
            {
                Message = "This theme uses custom animations but doesn't have custom group in the layouts, this means that the nxtheme will work on the firmware it has been developed on but it may break on older or newer ones. It's *highly recommended* to create custom groups to handle animations";
            }

            var targetPatch = SzsPatcher.DetectSarc(original, DefaultTemplates.templates);

            return(new LayoutPatch()
            {
                PatchName = "diffPatch" + (targetPatch == null ? "" : " for " + targetPatch.TemplateName),
                TargetName = targetPatch?.szsName,
                AuthorName = "autoDiff",
                Files = Patches.ToArray(),
                Anims = AnimPatches?.ToArray(),
                Ready8X = true
            }, Message);
        }
Ejemplo n.º 9
0
        private static void GetObjectInfos(Dictionary <string, List <ObjectInfo> > infosByListName, string levelName, string categoryName, SarcData sarc)
        {
            Dictionary <long, ObjectInfo> objectInfosByReference = new Dictionary <long, ObjectInfo>();

            if (sarc.Files.TryGetValue(levelName + categoryName + ".byml", out var data))
            {
                ByamlIterator byamlIter = new ByamlIterator(new MemoryStream(data));
#if ODYSSEY
                foreach (ArrayEntry scenario in byamlIter.IterRootArray())
                {
                    foreach (DictionaryEntry entry in scenario.IterDictionary())
                    {
                        if (!infosByListName.ContainsKey(entry.Key))
                        {
                            continue;
                        }

                        List <ObjectInfo> objectInfos = new List <ObjectInfo>();

                        foreach (ArrayEntry obj in entry.IterArray())
                        {
                            objectInfos.Add(ParseObjectInfo(obj, objectInfosByReference, infosByListName, entry.Key));
                        }
                    }
                }
#else
                foreach (DictionaryEntry entry in byamlIter.IterRootDictionary())
                {
                    if (!infosByListName.ContainsKey(entry.Key))
                    {
                        continue;
                    }

                    List <ObjectInfo> objectInfos = new List <ObjectInfo>();

                    foreach (ArrayEntry obj in entry.IterArray())
                    {
                        objectInfos.Add(ParseObjectInfo(obj, objectInfosByReference, infosByListName, entry.Key));
                    }
                }
#endif
            }
        }
Ejemplo n.º 10
0
        private void button4_Click(object sender, EventArgs e)
        {
            var Map_Data   = new Dictionary <string, byte[]>();
            var Sound_Data = new Dictionary <string, byte[]>();
            var new_dict   = new Dictionary <string, byte[]>();

            foreach (var item in Switch_Files)
            {
                if (!item.Key.EndsWith(".byml"))
                {
                    var m = new MemoryStream();
                    m.Write(item.Value, 0, item.Value.Length);
                    var b = m.ReadStream();
                    b.ByteOrder = ByteOrder.BigEndian;
                    var data = b.GetBytes();
                    b.Dispose();
                    m.Dispose();
                    new_dict.Add(item.Key, data);
                }
                else
                {
                    var f = new FileInfo(item.Key);
                    var m = new MemoryStream(item.Value);
                    var d = m.GetByml();
                    d.byteOrder = ByteOrder.BigEndian;
                    var data = d.GetBytes();
                    m.Dispose();
                    if (f.Name.Contains(Names.Camera) || f.Name.Contains(Names.Map))
                    {
                        Map_Data.Add(item.Key, data);
                    }
                    else if (f.Name.Contains(Names.Sound))
                    {
                        Sound_Data.Add(item.Key, data);
                    }
                    else
                    {
                        new_dict.Add(item.Key, data);
                    }
                }
            }
            var Design = new SarcData
            {
                HashOnly   = Hash,
                Files      = new_dict,
                endianness = ByteOrder.BigEndian
            };
            var Sound = new SarcData
            {
                HashOnly   = Hash,
                Files      = Sound_Data,
                endianness = ByteOrder.BigEndian
            };
            var Map = new SarcData
            {
                HashOnly   = Hash,
                Files      = Map_Data,
                endianness = ByteOrder.BigEndian
            };
            var Name = Switch_File.Name.Substring(0, Switch_File.Name.Length - 4);
            FolderBrowserDialog folder = new FolderBrowserDialog
            {
                UseDescriptionForTitle = true,
                Description            = "Select a folder to save the new Stage to.",
                RootFolder             = Environment.SpecialFolder.Recent,
                ShowNewFolderButton    = true
            };

            if (folder.ShowDialog().IsResult(DialogResult.OK))
            {
                Directory.SetCurrentDirectory(folder.SelectedPath);
                File.WriteAllBytes(Name + "Design1.szs", YAZ0.Compress(Design.PackSarcData().GetBytes()));
                File.WriteAllBytes(Name + "Sound1.szs", YAZ0.Compress(Sound.PackSarcData().GetBytes()));
                File.WriteAllBytes(Name + "Map1.szs", YAZ0.Compress(Map.PackSarcData().GetBytes()));
                MessageBox.Show("Complete!");
            }
        }
Ejemplo n.º 11
0
        public static LayoutPatch Diff(SarcData original, SarcData edited)
        {
            List <LayoutFilePatch> Patches = new List <LayoutFilePatch>();

            if (!ScrambledEquals <string>(original.Files.Keys, edited.Files.Keys))
            {
                MessageBox.Show("The provided archives don't have the same files");
                return(null);
            }
            var    targetPatch    = SwitchThemesCommon.DetectSarc(original, DefaultTemplates.templates);
            string skipLayoutName = targetPatch != null ? targetPatch.MainLayoutName : "";

            foreach (var f in original.Files.Keys.Where(x => x.EndsWith(".bflyt")))
            {
                if (original.Files[f].SequenceEqual(edited.Files[f]))
                {
                    continue;
                }
                BflytFile        or          = new BflytFile(original.Files[f]);
                BflytFile        ed          = new BflytFile(edited.Files[f]);
                string[]         orPaneNames = or.GetPaneNames();
                string[]         edPaneNames = ed.GetPaneNames();
                List <PanePatch> curFile     = new List <PanePatch>();
                for (int i = 0; i < edPaneNames.Length; i++)
                {
                    if (ed[i].data.Length < 0x4C || ed[i].name == "usd1")
                    {
                        continue;
                    }
                    if (f == skipLayoutName && targetPatch.targetPanels.Contains(edPaneNames[i]))
                    {
                        continue;
                    }
                    var j = Array.IndexOf(orPaneNames, edPaneNames[i]);
                    if (j == -1)
                    {
                        continue;
                    }
                    if (ed[i].data.SequenceEqual(or[j].data))
                    {
                        continue;
                    }
                    PanePatch curPatch = new PanePatch()
                    {
                        PaneName = edPaneNames[i]
                    };
                    var orPan = new BflytFile.PropertyEditablePanel(or[j]);
                    var edPan = new BflytFile.PropertyEditablePanel(ed[i]);
                    if (!VecEqual(edPan.Position, orPan.Position))
                    {
                        curPatch.Position = ToNullVec(edPan.Position);
                    }
                    if (!VecEqual(edPan.Rotation, orPan.Rotation))
                    {
                        curPatch.Rotation = ToNullVec(edPan.Rotation);
                    }
                    if (!VecEqual(edPan.Scale, orPan.Scale))
                    {
                        curPatch.Scale = ToNullVec(edPan.Scale);
                    }
                    if (!VecEqual(edPan.Size, orPan.Size))
                    {
                        curPatch.Size = ToNullVec(edPan.Size);
                    }
                    if (edPan.Visible != orPan.Visible)
                    {
                        curPatch.Visible = edPan.Visible;
                    }
                    if (edPan.name == "pic1")
                    {
                        if (edPan.ColorData[0] != orPan.ColorData[0])
                        {
                            curPatch.ColorTL = edPan.ColorData[0].ToString("X");
                        }
                        if (edPan.ColorData[1] != orPan.ColorData[1])
                        {
                            curPatch.ColorTR = edPan.ColorData[1].ToString("X");
                        }
                        if (edPan.ColorData[2] != orPan.ColorData[2])
                        {
                            curPatch.ColorBL = edPan.ColorData[2].ToString("X");
                        }
                        if (edPan.ColorData[3] != orPan.ColorData[3])
                        {
                            curPatch.ColorBR = edPan.ColorData[3].ToString("X");
                        }
                    }
                    curFile.Add(curPatch);
                }
                if (curFile.Count > 0)
                {
                    Patches.Add(new LayoutFilePatch()
                    {
                        FileName = f, Patches = curFile.ToArray()
                    });
                }
            }
            if (Patches.Count == 0)
            {
                MessageBox.Show("Couldn't find any difference");
                return(null);
            }
            return(new LayoutPatch()
            {
                PatchName = "diffPatch" + targetPatch == null ? "" : "for " + targetPatch.TemplateName,
                AuthorName = "autoDiff",
                Files = Patches.ToArray()
            });
        }
 public SzsPatcher(SarcData s) : this(s, DefaultTemplates.templates)
 {
 }
Ejemplo n.º 13
0
        public static LayoutPatch Diff(SarcData original, SarcData edited)
        {
            List <LayoutFilePatch> Patches = new List <LayoutFilePatch>();

            if (!ScrambledEquals <string>(original.Files.Keys, edited.Files.Keys))
            {
                MessageBox.Show("The provided archives don't have the same files");
                return(null);
            }
            var    targetPatch    = SwitchThemesCommon.DetectSarc(original, DefaultTemplates.templates);
            string skipLayoutName = targetPatch != null ? targetPatch.MainLayoutName : "";

            bool hasAtLeastAnExtraGroup = false;             //Used to detect if animations are properly implemented

            foreach (var f in original.Files.Keys.Where(x => x.EndsWith(".bflyt")))
            {
                if (original.Files[f].SequenceEqual(edited.Files[f]))
                {
                    continue;
                }
                BflytFile        or          = new BflytFile(original.Files[f]);
                BflytFile        ed          = new BflytFile(edited.Files[f]);
                string[]         orPaneNames = or.GetPaneNames();
                string[]         edPaneNames = ed.GetPaneNames();
                List <PanePatch> curFile     = new List <PanePatch>();
                for (int i = 0; i < edPaneNames.Length; i++)
                {
                    if (ed[i].data.Length < 0x4C || IgnorePaneList.Contains(ed[i].name))
                    {
                        continue;
                    }
                    if (f == skipLayoutName && (targetPatch?.targetPanels?.Contains(edPaneNames[i]) ?? false))
                    {
                        continue;
                    }
                    var j = Array.IndexOf(orPaneNames, edPaneNames[i]);
                    if (j == -1)
                    {
                        continue;
                    }

                    PanePatch curPatch = new PanePatch()
                    {
                        PaneName = edPaneNames[i]
                    };

                    curPatch.UsdPatches = MakeUsdPatch(or, i, ed, j);
                    if (ed[i].data.SequenceEqual(or[j].data))
                    {
                        if (curPatch.UsdPatches == null)
                        {
                            continue;
                        }
                        curFile.Add(curPatch);
                        continue;
                    }

                    var orPan = new BflytFile.PropertyEditablePanel(or[j]);
                    var edPan = new BflytFile.PropertyEditablePanel(ed[i]);
                    if (!VecEqual(edPan.Position, orPan.Position))
                    {
                        curPatch.Position = ToNullVec(edPan.Position);
                    }
                    if (!VecEqual(edPan.Rotation, orPan.Rotation))
                    {
                        curPatch.Rotation = ToNullVec(edPan.Rotation);
                    }
                    if (!VecEqual(edPan.Scale, orPan.Scale))
                    {
                        curPatch.Scale = ToNullVec(edPan.Scale);
                    }
                    if (!VecEqual(edPan.Size, orPan.Size))
                    {
                        curPatch.Size = ToNullVec(edPan.Size);
                    }
                    if (edPan.Visible != orPan.Visible)
                    {
                        curPatch.Visible = edPan.Visible;
                    }
                    if (edPan.name == "pic1")
                    {
                        if (edPan.ColorData[0] != orPan.ColorData[0])
                        {
                            curPatch.ColorTL = edPan.ColorData[0].ToString("X");
                        }
                        if (edPan.ColorData[1] != orPan.ColorData[1])
                        {
                            curPatch.ColorTR = edPan.ColorData[1].ToString("X");
                        }
                        if (edPan.ColorData[2] != orPan.ColorData[2])
                        {
                            curPatch.ColorBL = edPan.ColorData[2].ToString("X");
                        }
                        if (edPan.ColorData[3] != orPan.ColorData[3])
                        {
                            curPatch.ColorBR = edPan.ColorData[3].ToString("X");
                        }
                    }
                    curFile.Add(curPatch);
                }

                List <ExtraGroup> extraGroups = new List <ExtraGroup>();
                string[]          ogPanes     = or.GetGroupNames();
                foreach (var p_ in ed.Panels.Where(x => x is Grp1Pane))
                {
                    var p = ((Grp1Pane)p_);
                    if (ogPanes.Contains(p.GroupName))
                    {
                        continue;
                    }
                    extraGroups.Add(new ExtraGroup()
                    {
                        GroupName = p.GroupName, Panes = p.Panes.ToArray()
                    });
                    hasAtLeastAnExtraGroup = true;
                }
                if (extraGroups.Count == 0)
                {
                    extraGroups = null;
                }

                if (curFile.Count > 0 || extraGroups?.Count > 0)
                {
                    Patches.Add(new LayoutFilePatch()
                    {
                        FileName = f, Patches = curFile.ToArray(), AddGroups = extraGroups?.ToArray()
                    });
                }
            }
            if (Patches.Count == 0)             //animation edits depend on bflyt changes so this is relevant
            {
                MessageBox.Show("Couldn't find any difference");
                return(null);
            }

            List <AnimFilePatch> AnimPatches = new List <AnimFilePatch>();

            foreach (var f in original.Files.Keys.Where(x => x.EndsWith(".bflan")))
            {
                if (original.Files[f].SequenceEqual(edited.Files[f]))
                {
                    continue;
                }
                Bflan anim = new Bflan(edited.Files[f]);
                AnimPatches.Add(new AnimFilePatch()
                {
                    FileName = f, AnimJson = BflanSerializer.ToJson(anim)
                });
            }
            if (AnimPatches.Count == 0)
            {
                AnimPatches = null;
            }
            else if (!hasAtLeastAnExtraGroup)
            {
                MessageBox.Show("This theme uses custom animations but doesn't have custom group in the layouts, this means that the nxtheme will work on the firmware it has been developed on but it may break on older or newer ones. It's *highly recommended* to create custom groups to handle animations");
            }

            return(new LayoutPatch()
            {
                PatchName = "diffPatch" + (targetPatch == null ? "" : "for " + targetPatch.TemplateName),
                AuthorName = "autoDiff",
                Files = Patches.ToArray(),
                Anims = AnimPatches?.ToArray(),
                Ready8X = true                 //Aka tell the patcher to not fix this layout
            });
        }
Ejemplo n.º 14
0
        public static (LayoutPatch, string) Diff(SarcData original, SarcData edited)
        {
            List <LayoutFilePatch> Patches = new List <LayoutFilePatch>();

            if (!ScrambledEquals <string>(original.Files.Keys, edited.Files.Keys))
            {
                throw new Exception("The provided archives don't have the same files");
            }

            bool hasAtLeastAnExtraGroup = false;             //Used to detect if animations are properly implemented

            foreach (var f in original.Files.Keys.Where(x => x.EndsWith(".bflyt")))
            {
                if (original.Files[f].SequenceEqual(edited.Files[f]))
                {
                    continue;
                }
                BflytFile _or = new BflytFile(original.Files[f]);
                BflytFile _ed = new BflytFile(edited.Files[f]);

                var curFile = DiffPanes(_or, _ed, f);

                var extraGroups = DiffGroups(_or, _ed);
                if (extraGroups != null)
                {
                    hasAtLeastAnExtraGroup = true;
                }

                var materials = DiffMaterials(_or, _ed, f);

                if (curFile.Count > 0 || extraGroups?.Count > 0 || materials?.Count > 0)
                {
                    Patches.Add(new LayoutFilePatch()
                    {
                        FileName = f, Patches = curFile.ToArray(), Materials = materials?.ToArray(), AddGroups = extraGroups?.ToArray()
                    });
                }
            }
            if (Patches.Count == 0)             //animation edits depend on bflyt changes so this is relevant
            {
                throw new Exception("Couldn't find any difference");
            }

            string Message = null;

            List <AnimFilePatch> AnimPatches = new List <AnimFilePatch>();

            foreach (var f in original.Files.Keys.Where(x => x.EndsWith(".bflan")))
            {
                if (original.Files[f].SequenceEqual(edited.Files[f]))
                {
                    continue;
                }
                BflanFile anim = new BflanFile(edited.Files[f]);
                AnimPatches.Add(new AnimFilePatch()
                {
                    FileName = f, AnimJson = BflanSerializer.ToJson(anim)
                });
            }
            if (AnimPatches.Count == 0)
            {
                AnimPatches = null;
            }
            else if (!hasAtLeastAnExtraGroup)
            {
                Message = "This theme uses custom animations but doesn't have custom group in the layouts, this means that the nxtheme will work on the firmware it has been developed on but it may break on older or newer ones. It's *highly recommended* to create custom groups to handle animations";
            }

            var targetPatch = SzsPatcher.DetectSarc(original, DefaultTemplates.templates);

            return(new LayoutPatch()
            {
                PatchName = "diffPatch" + (targetPatch == null ? "" : " for " + targetPatch.TemplateName),
                TargetName = targetPatch?.szsName,
                AuthorName = "autoDiff",
                Files = Patches.ToArray(),
                Anims = AnimPatches?.ToArray(),
                ID = $"Generated_{Guid.NewGuid()}"
            }, Message);
        }
 public SzsPatcher(SarcData s, IEnumerable <PatchTemplate> t)
 {
     sarc      = s;
     templates = t;
 }
Ejemplo n.º 16
0
        public WorldMapScene(SarcData sarc, string sarcName)
        {
            multiSelect = true;

            #region read files
            this.sarc     = sarc;
            this.sarcName = sarcName;

            bfresEntry = sarc.Files.First(x => x.Key.EndsWith(".bfres"));

            pointEntry = sarc.Files.First(x => x.Key.StartsWith("pointW"));

            routeEntry = sarc.Files.First(x => x.Key.StartsWith("routeW"));

            bfres = new ResFile(new MemoryStream(bfresEntry.Value));
            bones = bfres.Models[0].Skeleton.Bones;

            pointCsv = Encoding.GetEncoding("shift-jis").GetString(sarc.Files.First(file => file.Key.StartsWith("pointW")).Value).
                       Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None).Reverse().Skip(1).Select(row =>
            {
                int pos = 0;
                List <string> fields = new List <string>();

                while (pos < row.Length)
                {
                    string value;

                    // Special handling for quoted field
                    if (row[pos] == '"')
                    {
                        // Skip initial quote
                        pos++;

                        // Parse quoted value
                        int start = pos;
                        while (pos < row.Length)
                        {
                            // Test for quote character
                            if (row[pos] == '"')
                            {
                                // Found one
                                pos++;

                                // If two quotes together, keep one
                                // Otherwise, indicates end of value
                                if (pos >= row.Length || row[pos] != '"')
                                {
                                    pos--;
                                    break;
                                }
                            }
                            pos++;
                        }
                        value = row.Substring(start, pos - start);
                        value = value.Replace("\"\"", "\"");
                    }
                    else
                    {
                        // Parse unquoted value
                        int start = pos;
                        while (pos < row.Length && row[pos] != ',')
                        {
                            pos++;
                        }
                        value = row.Substring(start, pos - start);
                    }

                    // Add field to list
                    fields.Add(value);

                    // Eat up to and including next comma
                    while (pos < row.Length && row[pos] != ',')
                    {
                        pos++;
                    }
                    if (pos < row.Length)
                    {
                        pos++;
                    }
                }

                return(fields.ToArray());
            }).Reverse().ToArray().ToDictionary(x => x[1]);

            routeCsv = Encoding.GetEncoding("shift-jis").GetString(sarc.Files.First(file => file.Key.StartsWith("routeW")).Value).
                       Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None).Reverse().Skip(1).Select(row =>
            {
                int pos = 0;
                List <string> fields = new List <string>();

                while (pos < row.Length)
                {
                    string value;

                    // Special handling for quoted field
                    if (row[pos] == '"')
                    {
                        // Skip initial quote
                        pos++;

                        // Parse quoted value
                        int start = pos;
                        while (pos < row.Length)
                        {
                            // Test for quote character
                            if (row[pos] == '"')
                            {
                                // Found one
                                pos++;

                                // If two quotes together, keep one
                                // Otherwise, indicates end of value
                                if (pos >= row.Length || row[pos] != '"')
                                {
                                    pos--;
                                    break;
                                }
                            }
                            pos++;
                        }
                        value = row.Substring(start, pos - start);
                        value = value.Replace("\"\"", "\"");
                    }
                    else
                    {
                        // Parse unquoted value
                        int start = pos;
                        while (pos < row.Length && row[pos] != ',')
                        {
                            pos++;
                        }
                        value = row.Substring(start, pos - start);
                    }

                    // Add field to list
                    fields.Add(value);

                    // Eat up to and including next comma
                    while (pos < row.Length && row[pos] != ',')
                    {
                        pos++;
                    }
                    if (pos < row.Length)
                    {
                        pos++;
                    }
                }

                return(fields.ToArray());
            }).Reverse().ToArray().ToDictionary(x => x[0]);


            //SaveFileDialog sfd = new SaveFileDialog()
            //{
            //    FileName = sarcName
            //};

            //if (sfd.ShowDialog() == DialogResult.OK)
            //{
            //    var stream = new MemoryStream();
            //    bfres.Save(stream, true);

            //    sarc.Files[bfresEntry.Key] = stream.ToArray();

            //    Yaz0.Compress(new FileStream(sfd.FileName, FileMode.OpenOrCreate), SARC.PackN(sarc));
            //}

            #endregion

            #region read map from bones
            Matrix4 rootMatrix = bones[0].CalculateRelativeMatrix();

            var boneIter = new BoneIter(bones);

            boneIter.MoveNext(); //first bone is the root, we don't need to read it

            while (boneIter.MoveNext())
            {
                var bone = boneIter.Current;

                if (bone.ParentIndex == -1) //there is more than one root (should never happen)
                {
                    break;
                }

                if (bone.Name.StartsWith("R")) //indicates a Route
                {
                    Routes.Add(new WorldMapRoute(boneIter, rootMatrix, pointCsv));
                    continue;
                }

                if (bone.ParentIndex != 0)
                {
                    throw new Exception(bone.Name + " is in an unexpected Layer, proceeding might currupt the file");
                }

                Vector4 pos = new Vector4(
                    bone.Position.X / 100,
                    bone.Position.Y / 100,
                    bone.Position.Z / 100,
                    1
                    );

                if (bone.Name == "course")
                {
                    Matrix4 courseBoneMatrix = boneIter.Current.CalculateRelativeMatrix() * rootMatrix;

                    short courseBoneIndex = (short)boneIter.CurrentBoneIndex;
                    while (boneIter.PeekNext()?.ParentIndex == courseBoneIndex)
                    {
                        boneIter.MoveNext();
                        if (pointCsv.ContainsKey(boneIter.Current.Name))
                        {
                            WorldMapObjects.Add(new WorldMapPoint(boneIter, courseBoneMatrix, pointCsv[boneIter.Current.Name]));
                        }
                        else
                        {
                            WorldMapObjects.Add(new UnknownWorldMapBone(boneIter, rootMatrix));
                        }
                    }
                }
                else if (pointCsv.ContainsKey(bone.Name))
                {
                    WorldMapObjects.Add(new WorldMapPoint(boneIter, rootMatrix, pointCsv[bone.Name]));
                }
                else if (bone.Name.StartsWith("cob"))
                {
                    WorldMapObjects.Add(new WorldMapCob(boneIter, rootMatrix));
                }
                else
                {
                    WorldMapObjects.Add(new UnknownWorldMapBone(boneIter, rootMatrix));
                }
            }
            #endregion

            foreach (var route in Routes)
            {
                TryGetPoint(route.Name.Substring(1, 4), out WorldMapPoint start);
                TryGetPoint(route.Name.Substring(5, 4), out WorldMapPoint end);

                route.Start = start;
                route.End   = end;
            }

            //ModelObjectReplace();

            StaticObjects.Add(new StaticModel(bfresEntry.Key, bfres));
            StaticObjects.Add(new ConnectionDrawer(this));

            SelectionChanged += WorldMapScene_SelectionChanged;
        }
Ejemplo n.º 17
0
 public SzsPatcher(SarcData s)
 {
     sarc = s;
 }
Ejemplo n.º 18
0
 /// <summary>
 /// Packs the SarcData.
 /// </summary>
 /// <param name="data">The SarcData to pack</param>
 /// <returns>A byte[] array of the packed data.</returns>
 public byte[] PackSarc(SarcData data)
 {
     return(data.PackSarcData().GetBytes());
 }