Decouple szs firmware detection from patch templates, add 11.0 fixes for old layouts. Animations are now patched as part of layouts.

This commit is contained in:
exelix11 2020-12-06 16:24:02 +01:00
parent 076f60e196
commit f7076ae497
12 changed files with 195 additions and 150 deletions

View File

@ -76,7 +76,6 @@
this.materialLabel10 = new MaterialSkin.Controls.MaterialLabel();
this.tbPatches = new System.Windows.Forms.TextBox();
this.InjectPage = new System.Windows.Forms.TabPage();
this.UseAnim = new System.Windows.Forms.CheckBox();
this.lblDetected = new MaterialSkin.Controls.MaterialLabel();
this.materialRaisedButton3 = new MaterialSkin.Controls.MaterialRaisedButton();
this.tbImageFile = new System.Windows.Forms.TextBox();
@ -780,7 +779,6 @@
// InjectPage
//
this.InjectPage.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(51)))), ((int)(((byte)(51)))), ((int)(((byte)(51)))));
this.InjectPage.Controls.Add(this.UseAnim);
this.InjectPage.Controls.Add(this.lblDetected);
this.InjectPage.Controls.Add(this.materialRaisedButton3);
this.InjectPage.Controls.Add(this.tbImageFile);
@ -801,18 +799,6 @@
this.InjectPage.TabIndex = 1;
this.InjectPage.Text = "SZS";
//
// UseAnim
//
this.UseAnim.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.UseAnim.AutoSize = true;
this.UseAnim.ForeColor = System.Drawing.Color.White;
this.UseAnim.Location = new System.Drawing.Point(3, 301);
this.UseAnim.Name = "UseAnim";
this.UseAnim.Size = new System.Drawing.Size(338, 17);
this.UseAnim.TabIndex = 6;
this.UseAnim.Text = "Do NOT add animations (Use if you have crashes with animations)";
this.UseAnim.UseVisualStyleBackColor = true;
//
// lblDetected
//
this.lblDetected.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
@ -1316,7 +1302,6 @@
private MaterialSkin.Controls.MaterialLabel lblAppletIcons;
private System.Windows.Forms.Label lblDebug;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.CheckBox UseAnim;
private System.Windows.Forms.Button btnApplet6;
private System.Windows.Forms.Button btnApplet5;
private System.Windows.Forms.Button btnApplet4;

View File

@ -18,7 +18,6 @@ namespace SwitchThemes
bool Advanced = false;
List<PatchTemplate> Templates = new List<PatchTemplate>();
Dictionary<string,LayoutPatch> Layouts = new Dictionary<string, LayoutPatch>();
public static Dictionary<string, string> HomeMenuParts = new Dictionary<string, string>()
@ -50,9 +49,6 @@ namespace SwitchThemes
//LayoutPatch.CreateTestTemplates();
//PatchTemplate.BuildTemplateFile();
Templates.AddRange(DefaultTemplates.templates);
if (File.Exists("ExtraTemplates.json"))
Templates.AddRange(PatchTemplate.LoadTemplates());
if (Directory.Exists("Layouts"))
{
foreach (var f in Directory.GetFiles("Layouts").Where(x => x.EndsWith(".json")))
@ -192,7 +188,7 @@ namespace SwitchThemes
{
#endif
string msg;
(res, msg) = LayoutDiff.Diff(originalSzs, CommonSzs);
(res, msg) = LayoutDiff.Diff(originalSzs, CommonSzs, null);
if (msg != null)
MessageBox.Show(msg);
#if !DEBUG
@ -307,7 +303,7 @@ namespace SwitchThemes
LayoutPatchList.Items.Add("Don't patch");
CommonSzs = SARCExt.SARC.Unpack(ManagedYaz0.Decompress(File.ReadAllBytes(opn.FileName)));
targetPatch = SzsPatcher.DetectSarc(CommonSzs, Templates);
targetPatch = DefaultTemplates.GetFor(CommonSzs);
if (targetPatch == null)
{
@ -397,7 +393,7 @@ namespace SwitchThemes
};
if (sav.ShowDialog() != DialogResult.OK) return;
SzsPatcher Patcher = new SzsPatcher(CommonSzs, Templates);
SzsPatcher Patcher = new SzsPatcher(CommonSzs);
var res = true;
if (HasImage)
@ -441,19 +437,12 @@ namespace SwitchThemes
if (LayoutPatchList.SelectedIndex != 0)
{
Patcher.EnableAnimations = !UseAnim.Checked;
var layoutres = Patcher.PatchLayouts(LayoutPatchList.SelectedItem as LayoutPatch);
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();

View File

@ -139,7 +139,7 @@ namespace SwitchThemes
string Target = args[1];
var CommonSzs = SARCExt.SARC.Unpack(ManagedYaz0.Decompress(File.ReadAllBytes(Target)));
var targetPatch = SzsPatcher.DetectSarc(CommonSzs, DefaultTemplates.templates);
var targetPatch = DefaultTemplates.GetFor(CommonSzs);
if (targetPatch == null)
{
@ -169,7 +169,7 @@ namespace SwitchThemes
try
{
var res = true;
var Patcher = new SzsPatcher(CommonSzs, DefaultTemplates.templates);
var Patcher = new SzsPatcher(CommonSzs);
if (Image != null)
{
@ -202,7 +202,6 @@ namespace SwitchThemes
if (Layout != null)
{
Patcher.EnableAnimations = true;
var l = LayoutPatch.LoadTemplate(File.ReadAllText(Layout));
var layoutres = Patcher.PatchLayouts(l);
if (!layoutres)
@ -210,7 +209,6 @@ namespace SwitchThemes
Console.WriteLine("One of the target files for the selected layout patch is missing in the SZS, you are probably using an already patched SZS");
return false;
}
layoutres = Patcher.PatchAnimations(l.Anims);
}
CommonSzs = Patcher.GetFinalSarc();

View File

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SwitchThemes.Common
{
public static class FirmwareDetection
{
public enum Firmware : int
{
Invariant = 0,
Fw5_0 = 1,
Fw6_0 = 2,
Fw7_0 = 3,
Fw8_0 = 4,
Fw9_0 = 5,
Fw10_0 = 6,
Fw11_0 = 7
}
struct FirmInfo
{
public Firmware Version;
public string[] MustContain;
public string[] MustNotContain;
}
readonly static IReadOnlyDictionary<string, FirmInfo[]> FirmwareInfo = new Dictionary<string, FirmInfo[]>
{
{ "home", new FirmInfo[] {
new FirmInfo() {
Version = Firmware.Fw11_0,
MustContain = new string[] { @"anim/RdtBase_SystemAppletPos.bflan" },
},
new FirmInfo() {
Version = Firmware.Fw8_0,
MustContain = new string[] { @"blyt/IconError.bflyt", @"blyt/RdtIconPromotion.bflyt" },
MustNotContain = new string[] { @"anim/RdtBtnShop_LimitB.bflan" }
},
new FirmInfo() {
Version = Firmware.Fw6_0,
MustContain = new string[] { @"blyt/IconError.bflyt" },
MustNotContain = new string[] { @"anim/RdtBtnShop_LimitB.bflan" }
},
new FirmInfo() {
Version = Firmware.Fw5_0,
MustContain = new string[] { @"anim/RdtBtnShop_LimitB.bflan" ,@"blyt/IconError.bflyt"}
} }
},
{ "lock", new FirmInfo[] {
new FirmInfo() {
Version = Firmware.Fw9_0,
MustContain = new string[] { @"blyt/PageindicatorAlarm.bflyt", @"blyt/EntBtnResumeSystemApplet.bflyt" },
} }
},
};
public static Firmware Detect(string nxPartName, SARCExt.SarcData sarc)
{
if (FirmwareInfo.ContainsKey(nxPartName))
{
var t = FirmwareInfo[nxPartName].Where(x =>
(x.MustContain?.All(y => sarc.Files.ContainsKey(y)) ?? true) &&
(x.MustNotContain?.All(y => !sarc.Files.ContainsKey(y)) ?? true)
);
if (t.Any())
return t.First().Version;
}
return Firmware.Invariant;
}
}
}

View File

@ -19,7 +19,12 @@ namespace SwitchThemes.Common
{
readonly static string[] IgnorePaneList = new string[] { "usd1", "lyt1", "mat1", "txl1", "fnl1", "grp1", "pae1", "pas1", "cnt1" };
public static (LayoutPatch,string) Diff(SarcData original, SarcData edited)
public struct DiffOptions
{
public bool? HideOnlineButton;
}
public static (LayoutPatch,string) Diff(SarcData original, SarcData edited, DiffOptions? opt)
{
List<LayoutFilePatch> Patches = new List<LayoutFilePatch>();
if (!ScrambledEquals<string>(original.Files.Keys, edited.Files.Keys))
@ -43,10 +48,6 @@ namespace SwitchThemes.Common
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;
@ -61,7 +62,7 @@ namespace SwitchThemes.Common
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);
var targetPatch = DefaultTemplates.GetFor(original);
return (new LayoutPatch()
{
@ -70,7 +71,8 @@ namespace SwitchThemes.Common
AuthorName = "autoDiff",
Files = Patches.ToArray(),
Anims = AnimPatches?.ToArray(),
ID = $"Generated_{Guid.NewGuid()}"
ID = $"Generated_{Guid.NewGuid()}",
HideOnlineBtn = opt?.HideOnlineButton ?? false
}, Message);
}
@ -141,7 +143,7 @@ namespace SwitchThemes.Common
WrapT = (byte)tx.WrapT
});
}
else throw new Exception($"A texture reference from the edited layout is missing in the original: {layoutname}");
else throw new Exception($"A texture reference to {tex} in the edited layout is not part of the original file: {layoutname}");
}
m.Transforms = transforms.Count == 0 ? null : transforms.ToArray();

View File

@ -13,7 +13,11 @@ namespace SwitchThemes.Common
public string AuthorName;
public string TargetName;
public string ID;
/* 11.0 added a new home menu button for online services, to show it it uses an animation that moves around all the applet buttons
if this flag is set to true or null the installer will automatically remove that animation emulating the layout of pre 11.0 qlaunch */
public bool? HideOnlineBtn;
[JsonIgnore]
public bool UsesOldFixes => ID == null && !Ready8X;
[Obsolete("This was used to detect whether a layout would need patches to support 8.0+ qlaunch, since version 4.5 prefer the ID value to detect layouts")]

View File

@ -2,31 +2,37 @@
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
using static SwitchThemes.Common.FirmwareDetection;
namespace SwitchThemes.Common
{
public static class NewFirmFixes
{
const string NoOnlineButton = "{\"PatchName\":\"NoOnline11\",\"Anims\":[{\"FileName\":\"anim/RdtBase_SystemAppletPos.bflan\",\"AnimJson\":\"{\\\"LittleEndian\\\":true,\\\"Version\\\":150994944,\\\"pat1\\\":{\\\"AnimationOrder\\\":6,\\\"Name\\\":\\\"SystemAppletPos\\\",\\\"ChildBinding\\\":190,\\\"Groups\\\":[\\\"G_System\\\"],\\\"Unk_StartOfFile\\\":0,\\\"Unk_EndOfFile\\\":0,\\\"Unk_EndOfHeader\\\":\\\"AL8AAAAAAA==\\\"},\\\"pai1\\\":{\\\"FrameSize\\\":1,\\\"Flags\\\":0,\\\"Textures\\\":[],\\\"Entries\\\":[]}}\"}]}";
/*
The RdtBase_SystemAppletPos animation on 11.0 will change the position and size of the applet buttons root element, to make layout developers' lives easier
this is automatically patched away. It's possible to override this by including that file in the layout json
*/
const string NoMoveApplets11 = "{\"PatchName\":\"G_SystemNoMove11.0\",\"Anims\":[{\"FileName\":\"anim/RdtBase_SystemAppletPos.bflan\",\"AnimJson\":\"{\\\"LittleEndian\\\":true,\\\"Version\\\":150994944,\\\"pat1\\\":{\\\"AnimationOrder\\\":6,\\\"Name\\\":\\\"SystemAppletPos\\\",\\\"ChildBinding\\\":190,\\\"Groups\\\":[\\\"G_System\\\"],\\\"Unk_StartOfFile\\\":0,\\\"Unk_EndOfFile\\\":0,\\\"Unk_EndOfHeader\\\":\\\"AL8AAAAAAA==\\\"},\\\"pai1\\\":{\\\"FrameSize\\\":1,\\\"Flags\\\":0,\\\"Textures\\\":[],\\\"Entries\\\":[{\\\"Name\\\":\\\"L_BtnLR\\\",\\\"Target\\\":0,\\\"Tags\\\":[{\\\"Unknown\\\":0,\\\"TagType\\\":\\\"FLVI\\\",\\\"Entries\\\":[{\\\"Index\\\":0,\\\"AnimationTarget\\\":0,\\\"DataType\\\":1,\\\"KeyFrames\\\":[{\\\"Frame\\\":0.0,\\\"Value\\\":0.0,\\\"Blend\\\":0.0},{\\\"Frame\\\":1.0,\\\"Value\\\":1.0,\\\"Blend\\\":0.0}],\\\"FLEUUnknownInt\\\":0,\\\"FLEUEntryName\\\":\\\"\\\"}]}],\\\"UnkwnownData\\\":\\\"\\\"}]}}\"}]}";
const string DogeLayoutFix = "{\"PatchName\":\"DogeLayout 8.x fix\",\"AuthorName\":\"autoDiff\",\"Files\":[{\"FileName\":\"blyt/HudTime.bflyt\",\"Patches\":[{\"PaneName\":\"N_AMPM\",\"Position\":{\"X\":30,\"Y\":-1,\"Z\":0},\"Scale\":{\"X\":0.9,\"Y\":0.9}}]},{\"FileName\":\"blyt/RdtBtnFullLauncher.bflyt\",\"Patches\":[{\"PaneName\":\"N_Tip\",\"Scale\":{\"X\":1.1,\"Y\":1.1}},{\"PaneName\":\"B_Hit\",\"Size\":{\"X\":80,\"Y\":80}}]},{\"FileName\":\"blyt/Cursor3.bflyt\",\"Patches\":[{\"PaneName\":\"P_Main\",\"UsdPatches\":[{\"PropName\":\"S_BorderSize\",\"PropValues\":[\"7\"],\"type\":2}]},{\"PaneName\":\"P_Grow\",\"UsdPatches\":[{\"PropName\":\"S_BorderSize\",\"PropValues\":[\"7\"],\"type\":2}]}]},{\"FileName\":\"blyt/RdtBtnMyPage.bflyt\",\"Patches\":[{\"PaneName\":\"N_Tip\",\"Position\":{\"X\":125,\"Y\":0,\"Z\":0}},{\"PaneName\":\"B_Hit\",\"Scale\":{\"X\":1.428571,\"Y\":1.428571},\"Size\":{\"X\":40,\"Y\":40}}]},{\"FileName\":\"blyt/RdtBtnIconGame.bflyt\",\"Patches\":[{\"PaneName\":\"RootPane\",\"Scale\":{\"X\":0.5,\"Y\":0.5}},{\"PaneName\":\"P_InnerCursor\",\"Visible\":false},{\"PaneName\":\"N_BtnFocusKey\",\"Size\":{\"X\":259,\"Y\":259}},{\"PaneName\":\"N_Tip\",\"Scale\":{\"X\":1.1,\"Y\":1.1}},{\"PaneName\":\"B_Hit\",\"Scale\":{\"X\":2,\"Y\":2},\"Size\":{\"X\":132,\"Y\":132}}]},{\"FileName\":\"blyt/RdtBase.bflyt\",\"Patches\":[{\"PaneName\":\"N_ScrollArea\",\"Position\":{\"X\":0,\"Y\":-218,\"Z\":0},\"Scale\":{\"X\":1,\"Y\":0.5},\"Size\":{\"X\":1300,\"Y\":322}},{\"PaneName\":\"N_ScrollWindow\",\"Position\":{\"X\":0,\"Y\":-218,\"Z\":0},\"Size\":{\"X\":100000,\"Y\":322}},{\"PaneName\":\"T_Blank\",\"Position\":{\"X\":0,\"Y\":197,\"Z\":0}},{\"PaneName\":\"N_GameRoot\",\"Position\":{\"X\":-530,\"Y\":-218,\"Z\":0},\"Scale\":{\"X\":0.00001,\"Y\":1}},{\"PaneName\":\"N_Game\",\"Position\":{\"X\":0,\"Y\":0,\"Z\":0},\"Scale\":{\"X\":100000,\"Y\":1}},{\"PaneName\":\"N_Icon_01\",\"Position\":{\"X\":135,\"Y\":0,\"Z\":0}},{\"PaneName\":\"N_Icon_02\",\"Position\":{\"X\":270,\"Y\":0,\"Z\":0}},{\"PaneName\":\"N_Icon_03\",\"Position\":{\"X\":405,\"Y\":0,\"Z\":0}},{\"PaneName\":\"N_Icon_04\",\"Position\":{\"X\":540,\"Y\":0,\"Z\":0}},{\"PaneName\":\"N_Icon_05\",\"Position\":{\"X\":675,\"Y\":0,\"Z\":0}},{\"PaneName\":\"N_Icon_06\",\"Position\":{\"X\":810,\"Y\":0,\"Z\":0}},{\"PaneName\":\"N_Icon_07\",\"Position\":{\"X\":945,\"Y\":0,\"Z\":0}},{\"PaneName\":\"N_Icon_08\",\"Position\":{\"X\":1,\"Y\":99999,\"Z\":0}},{\"PaneName\":\"N_Icon_09\",\"Position\":{\"X\":1,\"Y\":99999,\"Z\":0}},{\"PaneName\":\"N_Icon_10\",\"Position\":{\"X\":1,\"Y\":99999,\"Z\":0}},{\"PaneName\":\"N_Icon_11\",\"Position\":{\"X\":1,\"Y\":99999,\"Z\":0}},{\"PaneName\":\"N_Icon_12\",\"Position\":{\"X\":1080,\"Y\":0,\"Z\":0},\"Scale\":{\"X\":1,\"Y\":1}},{\"PaneName\":\"L_BtnFlc\",\"Scale\":{\"X\":0.5,\"Y\":0.5}}]},{\"FileName\":\"blyt/Hud.bflyt\",\"Patches\":[{\"PaneName\":\"N_Time\",\"Size\":{\"X\":12,\"Y\":30}},{\"PaneName\":\"L_Time\",\"Position\":{\"X\":-18,\"Y\":0,\"Z\":0}}]}]}";
const string DiamondFix = "{\"PatchName\":\"Diamond 8 fix\",\"AuthorName\":\"akai\",\"Files\":[{\"FileName\":\"blyt/RdtBtnFullLauncher.bflyt\",\"Patches\":[{\"PaneName\":\"N_Root\",\"Rotation\":{\"X\":0,\"Y\":0,\"Z\":45}}]},{\"FileName\":\"blyt/RdtBtnIconGame.bflyt\",\"Patches\":[{\"PaneName\":\"RootPane\",\"Scale\":{\"X\":0.37,\"Y\":0.37}},{\"PaneName\":\"B_Hit\",\"Scale\":{\"X\":3,\"Y\":3},\"Size\":{\"X\":97.68,\"Y\":97.68}}]},{\"FileName\":\"blyt/RdtBase.bflyt\",\"Patches\":[{\"PaneName\":\"N_ScrollArea\",\"Position\":{\"X\":-30,\"Y\":-200,\"Z\":0},\"Size\":{\"X\":1300,\"Y\":322}},{\"PaneName\":\"N_ScrollWindow\",\"Position\":{\"X\":-30,\"Y\":-200,\"Z\":0},\"Size\":{\"X\":1080,\"Y\":322}},{\"PaneName\":\"N_GameRoot\",\"Position\":{\"X\":200,\"Y\":-195,\"Z\":0},\"Scale\":{\"X\":0.00001,\"Y\":1}},{\"PaneName\":\"N_Game\",\"Position\":{\"X\":0,\"Y\":0,\"Z\":0},\"Scale\":{\"X\":100000,\"Y\":1}},{\"PaneName\":\"N_Icon_01\",\"Position\":{\"X\":140,\"Y\":0,\"Z\":0}},{\"PaneName\":\"N_Icon_02\",\"Position\":{\"X\":280,\"Y\":0,\"Z\":0}},{\"PaneName\":\"N_Icon_03\",\"Position\":{\"X\":68,\"Y\":73,\"Z\":0}},{\"PaneName\":\"N_Icon_04\",\"Position\":{\"X\":208,\"Y\":73,\"Z\":0}},{\"PaneName\":\"N_Icon_05\",\"Position\":{\"X\":1,\"Y\":99999,\"Z\":0}},{\"PaneName\":\"N_Icon_06\",\"Position\":{\"X\":1,\"Y\":99999,\"Z\":0}},{\"PaneName\":\"N_Icon_07\",\"Position\":{\"X\":1,\"Y\":99999,\"Z\":0}},{\"PaneName\":\"N_Icon_08\",\"Position\":{\"X\":1,\"Y\":99999,\"Z\":0}},{\"PaneName\":\"N_Icon_09\",\"Position\":{\"X\":1,\"Y\":99999,\"Z\":0}},{\"PaneName\":\"N_Icon_10\",\"Position\":{\"X\":1,\"Y\":99999,\"Z\":0}},{\"PaneName\":\"N_Icon_11\",\"Position\":{\"X\":1,\"Y\":99999,\"Z\":0}},{\"PaneName\":\"N_Icon_12\",\"Position\":{\"X\":348,\"Y\":73,\"Z\":0}},{\"PaneName\":\"L_BtnFlc\",\"Scale\":{\"X\":0.37,\"Y\":0.37}},{\"PaneName\":\"N_System\",\"Position\":{\"X\":-600,\"Y\":-250,\"Z\":0}},{\"PaneName\":\"L_BtnAccount_00\",\"Position\":{\"X\":-247,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_BtnAccount_01\",\"Position\":{\"X\":-175,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_BtnAccount_02\",\"Position\":{\"X\":-103,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_BtnAccount_03\",\"Position\":{\"X\":-31,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_BtnAccount_04\",\"Position\":{\"X\":41,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_BtnAccount_05\",\"Position\":{\"X\":113,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_BtnAccount_06\",\"Position\":{\"X\":185,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_Hud\",\"Position\":{\"X\":-300,\"Y\":-325,\"Z\":0}}]},{\"FileName\":\"blyt/Hud.bflyt\",\"Patches\":[{\"PaneName\":\"N_Time\",\"Position\":{\"X\":10,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_Time\",\"Position\":{\"X\":0,\"Y\":0,\"Z\":0}}]}]}";
const string CompactFix = "{\"PatchName\":\"Compact 8 fix\",\"AuthorName\":\"akai\",\"Files\":[{\"FileName\":\"blyt/RdtBtnFullLauncher.bflyt\",\"Patches\":[{\"PaneName\":\"N_Root\",\"Rotation\":{\"X\":0,\"Y\":0,\"Z\":45}}]},{\"FileName\":\"blyt/RdtBtnIconGame.bflyt\",\"Patches\":[{\"PaneName\":\"RootPane\",\"Scale\":{\"X\":0.37,\"Y\":0.37}},{\"PaneName\":\"B_Hit\",\"Scale\":{\"X\":3,\"Y\":3},\"Size\":{\"X\":97.68,\"Y\":97.68}}]},{\"FileName\":\"blyt/RdtBase.bflyt\",\"Patches\":[{\"PaneName\":\"N_ScrollArea\",\"Position\":{\"X\":0,\"Y\":-280,\"Z\":0},\"Scale\":{\"X\":1,\"Y\":0.5},\"Size\":{\"X\":1300,\"Y\":322}},{\"PaneName\":\"N_ScrollWindow\",\"Position\":{\"X\":0,\"Y\":-280,\"Z\":0},\"Scale\":{\"X\":1,\"Y\":0.5},\"Size\":{\"X\":1080,\"Y\":322}},{\"PaneName\":\"N_GameRoot\",\"Position\":{\"X\":-50,\"Y\":-230,\"Z\":0},\"Scale\":{\"X\":0.000001,\"Y\":1}},{\"PaneName\":\"N_Game\",\"Position\":{\"X\":0,\"Y\":0,\"Z\":0},\"Scale\":{\"X\":1000000,\"Y\":1}},{\"PaneName\":\"N_Icon_01\",\"Position\":{\"X\":100,\"Y\":0,\"Z\":0}},{\"PaneName\":\"N_Icon_02\",\"Position\":{\"X\":200,\"Y\":0,\"Z\":0}},{\"PaneName\":\"N_Icon_03\",\"Position\":{\"X\":300,\"Y\":0,\"Z\":0}},{\"PaneName\":\"N_Icon_04\",\"Position\":{\"X\":400,\"Y\":0,\"Z\":0}},{\"PaneName\":\"N_Icon_05\",\"Position\":{\"X\":500,\"Y\":0,\"Z\":0},\"Visible\":true},{\"PaneName\":\"N_Icon_06\",\"Position\":{\"X\":1,\"Y\":-9999999,\"Z\":0}},{\"PaneName\":\"N_Icon_07\",\"Position\":{\"X\":1,\"Y\":-9999999,\"Z\":0}},{\"PaneName\":\"N_Icon_08\",\"Position\":{\"X\":1,\"Y\":-9999999,\"Z\":0}},{\"PaneName\":\"N_Icon_09\",\"Position\":{\"X\":1,\"Y\":-9999999,\"Z\":0}},{\"PaneName\":\"N_Icon_10\",\"Position\":{\"X\":1,\"Y\":-9999999,\"Z\":0}},{\"PaneName\":\"N_Icon_11\",\"Position\":{\"X\":1,\"Y\":-9999999,\"Z\":0}},{\"PaneName\":\"N_Icon_12\",\"Position\":{\"X\":600,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_BtnFlc\",\"Scale\":{\"X\":0.37,\"Y\":0.37}},{\"PaneName\":\"L_BtnAccount_00\",\"Position\":{\"X\":-247,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_BtnAccount_01\",\"Position\":{\"X\":-175,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_BtnAccount_02\",\"Position\":{\"X\":-103,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_BtnAccount_03\",\"Position\":{\"X\":-31,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_BtnAccount_04\",\"Position\":{\"X\":41,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_BtnAccount_05\",\"Position\":{\"X\":113,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_BtnAccount_06\",\"Position\":{\"X\":185,\"Y\":0,\"Z\":0}},{\"PaneName\":\"L_Hud\",\"Position\":{\"X\":-290,\"Y\":-325,\"Z\":0}}]},{\"FileName\":\"blyt/Hud.bflyt\",\"Patches\":[{\"PaneName\":\"N_Time\",\"Position\":{\"X\":10,\"Y\":0,\"Z\":0}}]}]}";
const string ClearLock9Fix = "{\"PatchName\":\"clearlayout 9.x fix\",\"AuthorName\":\"exelix\",\"Ready8X\":true,\"Files\":[{\"FileName\":\"blyt/EntMain.bflyt\",\"Patches\":[{\"PaneName\":\"L_BtnResume\",\"Position\":{\"X\":-180,\"Y\":0,\"Z\":0}},{\"PaneName\":\"N_CntHud\",\"Position\":{\"X\":0,\"Y\":0,\"Z\":0}}]}]}";
public static LayoutFilePatch[] GetFixLegacy(string LayoutName, PatchTemplate context) => GetFixLegacy(LayoutName, context.PatchRevision, context.NXThemeName);
public static LayoutFilePatch[] GetFixLegacy(string LayoutName, int PatchRevision, string NXThemeName)
public static LayoutFilePatch[] GetFixLegacy(string LayoutName, Firmware fw, string nxName)
{
// Check PatchRevision definitions in PatchTemplte.cs for firmware version
if (PatchRevision >= 1 && NXThemeName == "lock") // >= 9.0 lock screen
if (fw >= Firmware.Fw9_0 && nxName == "lock")
{
if (LayoutName.ToLower().Contains("clear lockscreen"))
return JsonConvert.DeserializeObject<LayoutPatch>(ClearLock9Fix).Files;
}
// These are have all been updated in the builtins as of 4.4
if (PatchRevision >= 2 && NXThemeName == "home") // >= 8.0 home menu
if (fw >= Firmware.Fw8_0 && nxName == "home") // >= 8.0 home menu
{
if (LayoutName.ToLower().Contains("dogelayout") || LayoutName.ToLower().Contains("clearlayout"))
return JsonConvert.DeserializeObject<LayoutPatch>(DogeLayoutFix).Files;
@ -38,13 +44,29 @@ namespace SwitchThemes.Common
return null;
}
public static LayoutFilePatch[] GetFix(string NxPart, string LayoutID, int PatchRevision)
public static LayoutFilePatch[] GetFix(string NxPart, string LayoutID, Firmware fw)
{
// As of 4.5 this still hasn't been fixed in the builtin layouts but it has been given an ID
if (PatchRevision >= 1 && LayoutID == "builtin_ClearLock" && NxPart == "lock") /* Do we need NxPart ? */
if (fw >= Firmware.Fw9_0 && LayoutID == "builtin_ClearLock" && NxPart == "lock") /* Do we need NxPart ? */
return JsonConvert.DeserializeObject<LayoutPatch>(ClearLock9Fix).Files;
return null;
}
public static AnimFilePatch[] GetNoOnlineButtonFix(Firmware fw)
{
if (fw >= Firmware.Fw11_0)
return JsonConvert.DeserializeObject<LayoutPatch>(NoOnlineButton).Anims;
return null;
}
public static AnimFilePatch[] GetAppletsPositionFix(Firmware fw)
{
if (fw >= Firmware.Fw11_0)
return JsonConvert.DeserializeObject<LayoutPatch>(NoMoveApplets11).Anims;
return null;
}
}
}

View File

@ -26,7 +26,7 @@ namespace SwitchThemes.Common
Deprecated files:
Preview.png - an image used for previewing the dds, not supported anymore as the installer now can load the dds directly
*/
*/
public class ThemeFileManifest
{
@ -76,7 +76,6 @@ namespace SwitchThemes.Common
//public PatchTemplate[] UnpatchTargets;
public bool RequiresCodePatch = false;
public int PatchRevision = 0;
#if WIN
#if DEBUG
@ -90,7 +89,7 @@ namespace SwitchThemes.Common
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
};
string json = JsonConvert.SerializeObject(DefaultTemplates.templates, settings);
string json = JsonConvert.SerializeObject(DefaultTemplates.Templates, settings);
System.IO.File.WriteAllText("DefaultTemplates.json", json);
}
#endif
@ -101,8 +100,21 @@ namespace SwitchThemes.Common
public static class DefaultTemplates
{
// Whenever a new firmware breaks compatibility or layouts add a way to detect the new file here and increase the PatchRevision value, this is used later to fix old layouts via NewFirmFixes.cs
public static readonly PatchTemplate[] templates =
public static PatchTemplate GetFor(SARCExt.SarcData sarc)
{
bool SzsHasKey(string key) => sarc.Files.ContainsKey(key);
if (!SzsHasKey(@"timg/__Combined.bntx"))
return null;
var t = Templates.Where(x =>
x.FnameIdentifier.All(SzsHasKey) &&
!x.FnameNotIdentifier.Any(SzsHasKey));
return t.FirstOrDefault();
}
public static readonly PatchTemplate[] Templates =
{
//Common:
new PatchTemplate() { TemplateName = "home and applets" , szsName = "common.szs", TitleId = "0100000000001000", FirmName = "<= 5.X",
@ -116,17 +128,7 @@ namespace SwitchThemes.Common
NXThemeName = "home",
},
//Residentmenu:
new PatchTemplate() { TemplateName = "home menu" , szsName = "ResidentMenu.szs", TitleId = "0100000000001000", FirmName = ">= 8.0", PatchRevision = 2,
FnameIdentifier = new string[] { @"blyt/IconError.bflyt", @"blyt/RdtIconPromotion.bflyt" },
FnameNotIdentifier = new string[] { @"anim/RdtBtnShop_LimitB.bflan" } ,
MainLayoutName = @"blyt/BgNml.bflyt",
MaintextureName = "White1x1A128^s",
PatchIdentifier = "exelixBG",
targetPanels = new string[] { "P_Bg_00" },
SecondaryTexReplace = "White1x1A64^t",
NXThemeName = "home"
},
new PatchTemplate() { TemplateName = "home menu" , szsName = "ResidentMenu.szs", TitleId = "0100000000001000", FirmName = ">= 6.0, < 8.0", PatchRevision = 1,
new PatchTemplate() { TemplateName = "home menu" , szsName = "ResidentMenu.szs", TitleId = "0100000000001000", FirmName = ">= 6.0",
FnameIdentifier = new string[] { @"blyt/IconError.bflyt" },
FnameNotIdentifier = new string[] { @"anim/RdtBtnShop_LimitB.bflan" } ,
MainLayoutName = @"blyt/BgNml.bflyt",
@ -147,7 +149,7 @@ namespace SwitchThemes.Common
NXThemeName = "home"
},
//Entrance:
new PatchTemplate() { TemplateName = "lock screen" , szsName = "Entrance.szs", TitleId = "0100000000001000", FirmName = ">= 9.0", PatchRevision = 1,
new PatchTemplate() { TemplateName = "lock screen" , szsName = "Entrance.szs", TitleId = "0100000000001000", FirmName = ">= 9.0",
FnameIdentifier = new string[] { @"blyt/PageindicatorAlarm.bflyt", @"blyt/EntBtnResumeSystemApplet.bflyt"},
FnameNotIdentifier = new string[] { } ,
MainLayoutName =@"blyt/EntMain.bflyt",
@ -158,7 +160,7 @@ namespace SwitchThemes.Common
NXThemeName = "lock",
RequiresCodePatch = true,
},
new PatchTemplate() { TemplateName = "lock screen" , szsName = "Entrance.szs", TitleId = "0100000000001000", FirmName = "<= 8.X",
new PatchTemplate() { TemplateName = "lock screen" , szsName = "Entrance.szs", TitleId = "0100000000001000", FirmName = "<= 8.0",
FnameIdentifier = new string[] { @"blyt/EntBtnResumeSystemApplet.bflyt"},
FnameNotIdentifier = new string[] { @"blyt/PageindicatorAlarm.bflyt" } ,
MainLayoutName =@"blyt/EntMain.bflyt",

View File

@ -119,20 +119,14 @@ namespace SwitchThemes.Common
{
private SarcData sarc;
private QuickBntx bntx = null;
private IEnumerable<PatchTemplate> templates;
public bool EnableAnimations = true;
public bool EnablePaneOrderMod = true;
public SzsPatcher(SarcData s, IEnumerable<PatchTemplate> t)
public SzsPatcher(SarcData s)
{
sarc = s;
templates = t;
}
public SzsPatcher(SarcData s) : this(s, DefaultTemplates.templates)
{ }
void SaveBntx()
{
if (bntx == null) return;
@ -153,43 +147,21 @@ namespace SwitchThemes.Common
return sarc;
}
public bool PatchAnimations(AnimFilePatch[] files)
{
if (files == null) return true;
uint TargetVersion = 0;
foreach (var p in files)
{
if (!sarc.Files.ContainsKey(p.FileName))
continue; //return bool.Fail; Don't be so strict as older firmwares may not have all the animations (?)
if (TargetVersion == 0)
{
BflanFile b = new BflanFile(sarc.Files[p.FileName]);
TargetVersion = b.Version;
}
var n = BflanSerializer.FromJson(p.AnimJson);
n.Version = TargetVersion;
n.byteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
sarc.Files[p.FileName] = n.WriteFile();
}
return true;
}
private bool PatchSingleLayout(LayoutFilePatch p)
{
if (p == null || p.FileName == null) return true;
if (!sarc.Files.ContainsKey(p.FileName))
return false;
var target = new BflytFile(sarc.Files[p.FileName]);
target.ApplyMaterialsPatch(p.Materials); //Do not check result as it fails only if the file doesn't have any material
var res = target.ApplyLayoutPatch(p.Patches);
if (!res) return res;
if (EnableAnimations)
{
res = target.AddGroupNames(p.AddGroups);
if (!res) return res;
}
res = target.AddGroupNames(p.AddGroups);
if (!res) return res;
if (p.PullFrontPanes != null)
foreach (var n in p.PullFrontPanes)
@ -203,13 +175,12 @@ namespace SwitchThemes.Common
}
public bool PatchLayouts(LayoutPatch Patch) =>
PatchLayouts(Patch, PatchTemplate);
public bool PatchLayouts(LayoutPatch Patch, PatchTemplate context) =>
PatchLayouts(Patch, context?.NXThemeName ?? "", context?.PatchRevision ?? 0);
PatchLayouts(Patch, PatchTemplate?.NXThemeName ?? "");
public bool PatchLayouts(LayoutPatch Patch, string PartName, int PatchRevision)
public bool PatchLayouts(LayoutPatch Patch, string PartName)
{
var fw = FirmwareDetection.Detect(PartName, sarc);
if (PartName == "home" && Patch.PatchAppletColorAttrib)
PatchBntxTextureAttribs(new Tuple<string, uint>("RdtIcoPvr_00^s", 0x5050505),
new Tuple<string, uint>("RdtIcoNews_00^s", 0x5050505), new Tuple<string, uint>("RdtIcoNews_01^s", 0x5050505),
@ -222,16 +193,16 @@ namespace SwitchThemes.Common
LayoutFilePatch[] extra;
//Legacy fixes based on name and version
if (PatchRevision != 0 && Patch.UsesOldFixes)
if (fw != FirmwareDetection.Firmware.Invariant && Patch.UsesOldFixes)
{
extra = NewFirmFixes.GetFixLegacy(Patch.PatchName, PatchRevision, PartName);
extra = NewFirmFixes.GetFixLegacy(Patch.PatchName, fw, PartName);
if (extra != null)
Files.AddRange(extra);
}
//Modern fixes based on layout ID
else if (Patch.ID != null)
{
extra = NewFirmFixes.GetFix(PartName, Patch.ID, PatchRevision);
extra = NewFirmFixes.GetFix(PartName, Patch.ID, fw);
if (extra != null)
Files.AddRange(extra);
}
@ -241,6 +212,39 @@ namespace SwitchThemes.Common
var res = PatchSingleLayout(p);
if (!res) return res;
}
List<AnimFilePatch> Anims = new List<AnimFilePatch>();
if (Patch.Anims != null)
Anims.AddRange(Patch.Anims);
AnimFilePatch[] animExtra = null;
if (Patch.HideOnlineBtn ?? true)
animExtra = NewFirmFixes.GetNoOnlineButtonFix(fw);
else if (!Anims.Any(x => x.FileName == "anim/RdtBase_SystemAppletPos.bflan"))
animExtra = NewFirmFixes.GetAppletsPositionFix(fw);
if (animExtra != null)
Anims.AddRange(animExtra);
if (Anims.Any())
{
// The bflan version varies between firmwares, load a file from the list to detect the right one
BflanFile b = new BflanFile(sarc.Files[Anims[0].FileName]);
var TargetVersion = b.Version;
b = null;
foreach (var p in Anims)
{
if (!sarc.Files.ContainsKey(p.FileName))
continue;
var n = BflanSerializer.FromJson(p.AnimJson);
n.Version = TargetVersion;
n.byteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
sarc.Files[p.FileName] = n.WriteFile();
}
}
return true;
}
@ -334,44 +338,9 @@ namespace SwitchThemes.Common
get
{
if (_patch != null) return _patch;
_patch = DetectSarc(sarc, templates);
_patch = DefaultTemplates.GetFor(sarc);
return _patch;
}
}
public static PatchTemplate DetectSarc(SarcData sarc, IEnumerable<PatchTemplate> Templates)
{
bool SzsHasKey(string key) => sarc.Files.ContainsKey(key);
if (!SzsHasKey(@"timg/__Combined.bntx"))
return null;
foreach (var p in Templates)
{
if (!SzsHasKey(p.MainLayoutName))
continue;
bool isTarget = true;
foreach (string s in p.FnameIdentifier)
{
if (!SzsHasKey(s))
{
isTarget = false;
break;
}
}
if (!isTarget) continue;
foreach (string s in p.FnameNotIdentifier)
{
if (SzsHasKey(s))
{
isTarget = false;
break;
}
}
if (!isTarget) continue;
return p;
}
return null;
}
}
}

View File

@ -24,6 +24,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Bntx\BntxxFormats.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bntx\DDSEncoder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bntx\Texture.cs" />
<Compile Include="$(MSBuildThisFileDirectory)FirmwareDetection.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Images.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RGBAColor.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Exten.cs" />

View File

@ -35,14 +35,13 @@ namespace SwitchThemesCommonTests
string lyt = Util.Exists($"Source/{name}.json") ? Util.ReadString($"Source/{name}.json") : null;
SzsPatcher patcher = new SzsPatcher(src, SwitchThemes.Common.DefaultTemplates.templates);
SzsPatcher patcher = new SzsPatcher(src);
Assert.IsTrue(patcher.PatchMainBG(DDS));
if (lyt != null)
{
var l = LayoutPatch.LoadTemplate(lyt);
patcher.PatchLayouts(l, patcher.PatchTemplate);
patcher.PatchAnimations(l.Anims);
patcher.PatchLayouts(l);
}
var final = patcher.GetFinalSarc();

View File

@ -28,7 +28,7 @@ namespace SwitchThemesCommonTests
public void BgPaneInjection()
{
var bflyt = new BflytFile(Util.ReadData("Synthetic/bginjection.bflyt"));
var t = DefaultTemplates.templates.Where(x => x.szsName == "ResidentMenu.szs" && x.targetPanels.Contains("P_Bg_00")).First();
var t = DefaultTemplates.Templates.Where(x => x.szsName == "ResidentMenu.szs" && x.targetPanels.Contains("P_Bg_00")).First();
Assert.IsTrue(bflyt.PatchBgLayout(t));