From af81753721b40959e1e021ec3866979ce468b449 Mon Sep 17 00:00:00 2001 From: WorstAquaPlayer Date: Fri, 7 Jan 2022 10:38:44 -0300 Subject: [PATCH 1/7] Update to .NET 6 and project dependencies --- Mara.Generator/Mara.Generator.csproj | 2 +- Mara.Lib/Mara.Lib.csproj | 6 +++--- Mara.Patcher/Mara.Patcher.csproj | 2 +- Mara.Tester/Mara.Tester.csproj | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Mara.Generator/Mara.Generator.csproj b/Mara.Generator/Mara.Generator.csproj index 8b0ca65..18c2438 100644 --- a/Mara.Generator/Mara.Generator.csproj +++ b/Mara.Generator/Mara.Generator.csproj @@ -2,7 +2,7 @@ WinExe - net5.0-windows + net6.0-windows true diff --git a/Mara.Lib/Mara.Lib.csproj b/Mara.Lib/Mara.Lib.csproj index e1cc009..def3138 100644 --- a/Mara.Lib/Mara.Lib.csproj +++ b/Mara.Lib/Mara.Lib.csproj @@ -1,14 +1,14 @@ - net5.0 + net6.0 - + - + diff --git a/Mara.Patcher/Mara.Patcher.csproj b/Mara.Patcher/Mara.Patcher.csproj index 80c7c77..eaee386 100644 --- a/Mara.Patcher/Mara.Patcher.csproj +++ b/Mara.Patcher/Mara.Patcher.csproj @@ -1,6 +1,6 @@  - net5.0 + net6.0 diff --git a/Mara.Tester/Mara.Tester.csproj b/Mara.Tester/Mara.Tester.csproj index 40d934e..4b60bcb 100644 --- a/Mara.Tester/Mara.Tester.csproj +++ b/Mara.Tester/Mara.Tester.csproj @@ -2,7 +2,7 @@ Exe - net5.0 + net6.0 From c51de9c93cb46638a12951f045c921ca5e069b85 Mon Sep 17 00:00:00 2001 From: WorstAquaPlayer Date: Fri, 7 Jan 2022 14:02:33 -0300 Subject: [PATCH 2/7] Implemented general patch process for 3DS. Also removed XdeltaSharp.dll and added the XdeltaSharp Nuget. --- Mara.Lib/Common/Xdelta.cs | 2 +- Mara.Lib/Dll/Pleosoft.XdeltaSharp.deps.json | 120 -------------------- Mara.Lib/Dll/Pleosoft.XdeltaSharp.dll | Bin 23040 -> 0 bytes Mara.Lib/Dll/Pleosoft.XdeltaSharp.xml | 34 ------ Mara.Lib/Mara.Lib.csproj | 4 +- Mara.Lib/Platforms/3ds/Main.cs | 86 +++++++++++++- 6 files changed, 86 insertions(+), 160 deletions(-) delete mode 100644 Mara.Lib/Dll/Pleosoft.XdeltaSharp.deps.json delete mode 100644 Mara.Lib/Dll/Pleosoft.XdeltaSharp.dll delete mode 100644 Mara.Lib/Dll/Pleosoft.XdeltaSharp.xml diff --git a/Mara.Lib/Common/Xdelta.cs b/Mara.Lib/Common/Xdelta.cs index bf36abe..d15c6b3 100644 --- a/Mara.Lib/Common/Xdelta.cs +++ b/Mara.Lib/Common/Xdelta.cs @@ -1,5 +1,5 @@ using System.IO; -using Pleosoft.XdeltaSharp; +using PleOps.XdeltaSharp.Decoder; namespace Mara.Lib.Common { diff --git a/Mara.Lib/Dll/Pleosoft.XdeltaSharp.deps.json b/Mara.Lib/Dll/Pleosoft.XdeltaSharp.deps.json deleted file mode 100644 index 8413375..0000000 --- a/Mara.Lib/Dll/Pleosoft.XdeltaSharp.deps.json +++ /dev/null @@ -1,120 +0,0 @@ -{ - "runtimeTarget": { - "name": ".NETStandard,Version=v2.0/", - "signature": "" - }, - "compilationOptions": {}, - "targets": { - ".NETStandard,Version=v2.0": {}, - ".NETStandard,Version=v2.0/": { - "Pleosoft.XdeltaSharp/1.0.0": { - "dependencies": { - "Microsoft.SourceLink.GitHub": "1.0.0", - "NETStandard.Library": "2.0.3", - "Roslynator.Analyzers": "3.0.0", - "SonarAnalyzer.CSharp": "8.15.0.24505", - "StyleCop.Analyzers": "1.1.118", - "System.Buffers": "4.5.1" - }, - "runtime": { - "Pleosoft.XdeltaSharp.dll": {} - } - }, - "Microsoft.Build.Tasks.Git/1.0.0": {}, - "Microsoft.NETCore.Platforms/1.1.0": {}, - "Microsoft.SourceLink.Common/1.0.0": {}, - "Microsoft.SourceLink.GitHub/1.0.0": { - "dependencies": { - "Microsoft.Build.Tasks.Git": "1.0.0", - "Microsoft.SourceLink.Common": "1.0.0" - } - }, - "NETStandard.Library/2.0.3": { - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0" - } - }, - "Roslynator.Analyzers/3.0.0": {}, - "SonarAnalyzer.CSharp/8.15.0.24505": {}, - "StyleCop.Analyzers/1.1.118": {}, - "System.Buffers/4.5.1": { - "runtime": { - "lib/netstandard2.0/System.Buffers.dll": { - "assemblyVersion": "4.0.3.0", - "fileVersion": "4.6.28619.1" - } - } - } - } - }, - "libraries": { - "Pleosoft.XdeltaSharp/1.0.0": { - "type": "project", - "serviceable": false, - "sha512": "" - }, - "Microsoft.Build.Tasks.Git/1.0.0": { - "type": "package", - "serviceable": true, - "sha512": "sha512-z2fpmmt+1Jfl+ZnBki9nSP08S1/tbEOxFdsK1rSR+LBehIJz1Xv9/6qOOoGNqlwnAGGVGis1Oj6S8Kt9COEYlQ==", - "path": "microsoft.build.tasks.git/1.0.0", - "hashPath": "microsoft.build.tasks.git.1.0.0.nupkg.sha512" - }, - "Microsoft.NETCore.Platforms/1.1.0": { - "type": "package", - "serviceable": true, - "sha512": "sha512-kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==", - "path": "microsoft.netcore.platforms/1.1.0", - "hashPath": "microsoft.netcore.platforms.1.1.0.nupkg.sha512" - }, - "Microsoft.SourceLink.Common/1.0.0": { - "type": "package", - "serviceable": true, - "sha512": "sha512-G8DuQY8/DK5NN+3jm5wcMcd9QYD90UV7MiLmdljSJixi3U/vNaeBKmmXUqI4DJCOeWizIUEh4ALhSt58mR+5eg==", - "path": "microsoft.sourcelink.common/1.0.0", - "hashPath": "microsoft.sourcelink.common.1.0.0.nupkg.sha512" - }, - "Microsoft.SourceLink.GitHub/1.0.0": { - "type": "package", - "serviceable": true, - "sha512": "sha512-aZyGyGg2nFSxix+xMkPmlmZSsnGQ3w+mIG23LTxJZHN+GPwTQ5FpPgDo7RMOq+Kcf5D4hFWfXkGhoGstawX13Q==", - "path": "microsoft.sourcelink.github/1.0.0", - "hashPath": "microsoft.sourcelink.github.1.0.0.nupkg.sha512" - }, - "NETStandard.Library/2.0.3": { - "type": "package", - "serviceable": true, - "sha512": "sha512-st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", - "path": "netstandard.library/2.0.3", - "hashPath": "netstandard.library.2.0.3.nupkg.sha512" - }, - "Roslynator.Analyzers/3.0.0": { - "type": "package", - "serviceable": true, - "sha512": "sha512-UKaYNtbXGGkR83rMA42DbA43fIUebO+WfHvPk29WMZfXzzF9kTKEB0HL6dUmcukgeHwXyTBCj6946DSaoow02A==", - "path": "roslynator.analyzers/3.0.0", - "hashPath": "roslynator.analyzers.3.0.0.nupkg.sha512" - }, - "SonarAnalyzer.CSharp/8.15.0.24505": { - "type": "package", - "serviceable": true, - "sha512": "sha512-r4Pt4c/FV1m//NuvVP5k0PmGBceJTyV9hv0sGXSd2bpLb2I0yX3IShuGcCekkS2E82Gay5feKlfOK9b+G3vr1Q==", - "path": "sonaranalyzer.csharp/8.15.0.24505", - "hashPath": "sonaranalyzer.csharp.8.15.0.24505.nupkg.sha512" - }, - "StyleCop.Analyzers/1.1.118": { - "type": "package", - "serviceable": true, - "sha512": "sha512-Onx6ovGSqXSK07n/0eM3ZusiNdB6cIlJdabQhWGgJp3Vooy9AaLS/tigeybOJAobqbtggTamoWndz72JscZBvw==", - "path": "stylecop.analyzers/1.1.118", - "hashPath": "stylecop.analyzers.1.1.118.nupkg.sha512" - }, - "System.Buffers/4.5.1": { - "type": "package", - "serviceable": true, - "sha512": "sha512-Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==", - "path": "system.buffers/4.5.1", - "hashPath": "system.buffers.4.5.1.nupkg.sha512" - } - } -} \ No newline at end of file diff --git a/Mara.Lib/Dll/Pleosoft.XdeltaSharp.dll b/Mara.Lib/Dll/Pleosoft.XdeltaSharp.dll deleted file mode 100644 index f4e101e9ed4ffc2b95b4611f5e9b793e921ea9bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23040 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 diff --git a/Mara.Lib/Dll/Pleosoft.XdeltaSharp.xml b/Mara.Lib/Dll/Pleosoft.XdeltaSharp.xml deleted file mode 100644 index 6bfb571..0000000 --- a/Mara.Lib/Dll/Pleosoft.XdeltaSharp.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - Pleosoft.XdeltaSharp - - - - - Adler-32 checksum algorithm. - - - For more information: https://en.wikipedia.org/wiki/Adler-32. - - - - - Computes the checksum Adler-32 from a stream. - - The stream to read data. It starts at the current position. - The amount of bytes to read from the stream for the checksum. - The start value of the checksum. - The Adler-32 checksum of the data. - - - - Decodes an integer of variable length. - Defined in RCF-3284, the VCDIFF format uses a variable-length integer. - Each byte contains 7-bits of data and the last bit indicates if there - more bytes to decode. - - The integer. - - - diff --git a/Mara.Lib/Mara.Lib.csproj b/Mara.Lib/Mara.Lib.csproj index def3138..4ea488d 100644 --- a/Mara.Lib/Mara.Lib.csproj +++ b/Mara.Lib/Mara.Lib.csproj @@ -6,6 +6,7 @@ + @@ -19,9 +20,6 @@ Dll\LibHac.dll - - Dll\Pleosoft.XdeltaSharp.dll - diff --git a/Mara.Lib/Platforms/3ds/Main.cs b/Mara.Lib/Platforms/3ds/Main.cs index 593acdc..86aea90 100644 --- a/Mara.Lib/Platforms/3ds/Main.cs +++ b/Mara.Lib/Platforms/3ds/Main.cs @@ -1,12 +1,94 @@ -using System; +using SceneGate.Lemon.Containers.Converters; +using SceneGate.Lemon.Titles; +using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using Yarhl.FileSystem; +using Yarhl.IO; namespace Mara.Lib.Platforms._3ds { - class Main + public class Main : PatchProcess { + public PatchMode PatchMode { get; set; } + Node cia { get; set; } + Node programNode { get; set; } + + public Main(string oriFile, string outFile, string patchPath, PatchMode patchMode) : base(oriFile, outFile, patchPath) + { + PatchMode = patchMode; + + try + { + cia = NodeFactory.FromFile(oriFile, "root").TransformWith(); + } + catch (Exception ex) + { + throw new FormatException($"{Path.GetFileName(oriFile)} is an invalid CIA file.", ex); + } + + programNode = cia.Children["content"].Children["program"]; + if (programNode.Tags.ContainsKey("LEMON_NCCH_ENCRYPTED")) + { + throw new Exception("Encrypted (legit) CIA not supported"); + } + } + + public override (int, string) ApplyTranslation() + { + var count = maraConfig.FilesInfo.ListOriFiles.Length; + var files = maraConfig.FilesInfo; + + programNode.TransformWith(); + + switch (PatchMode) + { + case PatchMode.General: + foreach (var node in Navigator.IterateNodes(programNode)) + { + node.Stream.WriteTo(tempFolder + Path.DirectorySeparatorChar + node.Name); + } + + for (int i = 0; i < count; i++) + { + var file = $"{tempFolder}{Path.DirectorySeparatorChar}{files.ListOriFiles[i]}"; + var xdelta = $"{tempFolder}{Path.DirectorySeparatorChar}{files.ListXdeltaFiles[i]}"; + + var result = ApplyXdelta(file, xdelta, file, files.ListMd5Files[i]); + + if (result.Item1 != 0) + return result; + + programNode.Add(NodeFactory.FromFile(file, files.ListOriFiles[i])); + } + break; + case PatchMode.Specific: + throw new NotImplementedException(); + programNode.Children["rom"].TransformWith(); + programNode.Children["system"].TransformWith(); + } + + programNode.TransformWith(); + cia.TransformWith(); + + if (File.Exists(outFolder)) + { + File.Delete(outFolder); + } + + cia.Stream.WriteTo(outFolder); + cia.Stream?.Dispose(); + + return base.ApplyTranslation(); + } + } + + public enum PatchMode + { + General, + Specific } } From 6aa3182302c10158de19810fb8c116c4eb95efbb Mon Sep 17 00:00:00 2001 From: WorstAquaPlayer Date: Fri, 7 Jan 2022 16:02:39 -0300 Subject: [PATCH 3/7] Make possible to patch other nodes in "content" (such as manual) --- Mara.Lib/Platforms/3ds/Main.cs | 64 ++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/Mara.Lib/Platforms/3ds/Main.cs b/Mara.Lib/Platforms/3ds/Main.cs index 86aea90..0083cd3 100644 --- a/Mara.Lib/Platforms/3ds/Main.cs +++ b/Mara.Lib/Platforms/3ds/Main.cs @@ -14,8 +14,9 @@ namespace Mara.Lib.Platforms._3ds public class Main : PatchProcess { public PatchMode PatchMode { get; set; } - Node cia { get; set; } - Node programNode { get; set; } + Node Cia { get; set; } + Node ContentNode { get; set; } + List ContentToPatch = new List(); public Main(string oriFile, string outFile, string patchPath, PatchMode patchMode) : base(oriFile, outFile, patchPath) { @@ -23,17 +24,36 @@ public Main(string oriFile, string outFile, string patchPath, PatchMode patchMod try { - cia = NodeFactory.FromFile(oriFile, "root").TransformWith(); + Cia = NodeFactory.FromFile(oriFile, "root").TransformWith(); } catch (Exception ex) { - throw new FormatException($"{Path.GetFileName(oriFile)} is an invalid CIA file.", ex); + if (ex is FormatException) + { + throw new FormatException($"{Path.GetFileName(oriFile)} is an invalid CIA file.", ex); + } + else + { + throw new Exception($"An error has ocurred while reading the file.", ex); + } } - programNode = cia.Children["content"].Children["program"]; - if (programNode.Tags.ContainsKey("LEMON_NCCH_ENCRYPTED")) + ContentNode = Cia.Children["content"]; + + foreach (var content in ContentNode.Children) { - throw new Exception("Encrypted (legit) CIA not supported"); + if (content.Tags.ContainsKey("LEMON_NCCH_ENCRYPTED")) + { + throw new Exception("Encrypted (legit) CIA not supported"); + } + + for (int i = 0; i < maraConfig.FilesInfo.ListOriFiles.Length; i++) + { + if (maraConfig.FilesInfo.ListOriFiles[i].StartsWith(content.Name)) + { + ContentToPatch.Add(content.Name); + } + } } } @@ -42,14 +62,18 @@ public override (int, string) ApplyTranslation() var count = maraConfig.FilesInfo.ListOriFiles.Length; var files = maraConfig.FilesInfo; - programNode.TransformWith(); - switch (PatchMode) { case PatchMode.General: - foreach (var node in Navigator.IterateNodes(programNode)) + foreach (var contentToPatch in ContentToPatch) { - node.Stream.WriteTo(tempFolder + Path.DirectorySeparatorChar + node.Name); + var contentChildNode = ContentNode.Children[contentToPatch]; + contentChildNode.TransformWith(); + + foreach (var node in Navigator.IterateNodes(contentChildNode)) + { + node.Stream.WriteTo(tempFolder + Path.DirectorySeparatorChar + contentToPatch + Path.DirectorySeparatorChar + node.Name); + } } for (int i = 0; i < count; i++) @@ -62,25 +86,29 @@ public override (int, string) ApplyTranslation() if (result.Item1 != 0) return result; - programNode.Add(NodeFactory.FromFile(file, files.ListOriFiles[i])); + var content = files.ListOriFiles[i].Split('\\')[0]; + ContentNode.Children[content].Add(NodeFactory.FromFile(file, Path.GetFileName(files.ListOriFiles[i]))); + } + + foreach (var contentToPatch in ContentToPatch) + { + var contentChildNode = ContentNode.Children[contentToPatch]; + contentChildNode.TransformWith(); } break; case PatchMode.Specific: throw new NotImplementedException(); - programNode.Children["rom"].TransformWith(); - programNode.Children["system"].TransformWith(); } - programNode.TransformWith(); - cia.TransformWith(); + Cia.TransformWith(); if (File.Exists(outFolder)) { File.Delete(outFolder); } - cia.Stream.WriteTo(outFolder); - cia.Stream?.Dispose(); + Cia.Stream.WriteTo(outFolder); + Cia.Stream?.Dispose(); return base.ApplyTranslation(); } From e3a0cd9f984c6330168d9d6a0786f9c7d0181d33 Mon Sep 17 00:00:00 2001 From: WorstAquaPlayer Date: Fri, 7 Jan 2022 18:37:51 -0300 Subject: [PATCH 4/7] Implemented specific patch process for 3DS --- Mara.Lib/Platforms/3ds/Main.cs | 100 ++++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 7 deletions(-) diff --git a/Mara.Lib/Platforms/3ds/Main.cs b/Mara.Lib/Platforms/3ds/Main.cs index 0083cd3..3f36443 100644 --- a/Mara.Lib/Platforms/3ds/Main.cs +++ b/Mara.Lib/Platforms/3ds/Main.cs @@ -16,7 +16,7 @@ public class Main : PatchProcess public PatchMode PatchMode { get; set; } Node Cia { get; set; } Node ContentNode { get; set; } - List ContentToPatch = new List(); + Dictionary> ContentToPatch = new Dictionary>(); public Main(string oriFile, string outFile, string patchPath, PatchMode patchMode) : base(oriFile, outFile, patchPath) { @@ -49,9 +49,26 @@ public Main(string oriFile, string outFile, string patchPath, PatchMode patchMod for (int i = 0; i < maraConfig.FilesInfo.ListOriFiles.Length; i++) { - if (maraConfig.FilesInfo.ListOriFiles[i].StartsWith(content.Name)) + var splitLine = maraConfig.FilesInfo.ListOriFiles[i].Split('\\'); + + if (splitLine[0] == content.Name) { - ContentToPatch.Add(content.Name); + if (ContentToPatch.ContainsKey(splitLine[0])) + { + if (!ContentToPatch[splitLine[0]].Contains(splitLine[1])) + { + ContentToPatch[splitLine[0]].Add(splitLine[1]); + } + } + else + { + ContentToPatch.Add(splitLine[0], new List { splitLine[1] }); + } + + if (patchMode == PatchMode.Specific && splitLine[1] != "rom") + { + throw new FormatException($"Unsupported specific patching for {splitLine[1]}"); + } } } } @@ -67,12 +84,12 @@ public override (int, string) ApplyTranslation() case PatchMode.General: foreach (var contentToPatch in ContentToPatch) { - var contentChildNode = ContentNode.Children[contentToPatch]; + var contentChildNode = ContentNode.Children[contentToPatch.Key]; contentChildNode.TransformWith(); foreach (var node in Navigator.IterateNodes(contentChildNode)) { - node.Stream.WriteTo(tempFolder + Path.DirectorySeparatorChar + contentToPatch + Path.DirectorySeparatorChar + node.Name); + node.Stream.WriteTo(tempFolder + Path.DirectorySeparatorChar + contentToPatch.Key + Path.DirectorySeparatorChar + node.Name); } } @@ -92,12 +109,81 @@ public override (int, string) ApplyTranslation() foreach (var contentToPatch in ContentToPatch) { - var contentChildNode = ContentNode.Children[contentToPatch]; + var contentChildNode = ContentNode.Children[contentToPatch.Key]; contentChildNode.TransformWith(); } break; case PatchMode.Specific: - throw new NotImplementedException(); + foreach (var contentToPatch in ContentToPatch) + { + var contentNode = ContentNode.Children[contentToPatch.Key]; + contentNode.TransformWith(); + + foreach (var node in Navigator.IterateNodes(contentNode)) + { + switch(node.Name) + { + case "rom": + node.TransformWith(); + break; + } + + foreach(var nodeChild in Navigator.IterateNodes(node)) + { + var path = nodeChild.Path.Replace($"/root/content/{contentToPatch.Key}/", "").Replace('/', Path.DirectorySeparatorChar); + + // Using node.Stream will return null for some reason + var nodeChildFromRoot = Navigator.SearchNode(Cia, nodeChild.Path); + if (!nodeChildFromRoot.IsContainer) + { + nodeChildFromRoot.Stream.WriteTo(tempFolder + Path.DirectorySeparatorChar + contentToPatch.Key + Path.DirectorySeparatorChar + path); + } + } + } + } + + for (int i = 0; i < count; i++) + { + var file = $"{tempFolder}{Path.DirectorySeparatorChar}{files.ListOriFiles[i]}"; + var xdelta = $"{tempFolder}{Path.DirectorySeparatorChar}{files.ListXdeltaFiles[i]}"; + + var result = ApplyXdelta(file, xdelta, file, files.ListMd5Files[i]); + + if (result.Item1 != 0) + return result; + + // We need to delete these since later we're going to make a new Node container with this folder + if (File.Exists($"{file}_ori")) + { + File.Delete($"{file}_ori"); + } + + if (File.Exists(xdelta)) + { + File.Delete(xdelta); + } + } + + foreach (var contentToPatch in ContentToPatch) + { + var contentPath = $"{tempFolder}{Path.DirectorySeparatorChar}{contentToPatch.Key}{Path.DirectorySeparatorChar}"; + + foreach (var contentChild in ContentToPatch[contentToPatch.Key]) + { + var contentChildPath = $"{contentPath}{Path.DirectorySeparatorChar}{contentChild}"; + + switch (contentChild) + { + case "rom": + ContentNode.Children[contentToPatch.Key].Add(NodeFactory.FromDirectory(contentChildPath, "*", contentChild, true)); + ContentNode.Children[contentToPatch.Key].Children[contentChild].TransformWith(); + break; + } + } + + ContentNode.Children[contentToPatch.Key].TransformWith(); + } + break; } Cia.TransformWith(); From 9be9a749474b60004f4b2aa7b8b3bd44bcc218dd Mon Sep 17 00:00:00 2001 From: WorstAquaPlayer Date: Fri, 7 Jan 2022 19:05:17 -0300 Subject: [PATCH 5/7] Added test for 3DS the patching processes. To do this, the directory checking at the start was slightly modified since the 3DS relies on an input and output .cia file. --- Mara.Tester/Program.cs | 57 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/Mara.Tester/Program.cs b/Mara.Tester/Program.cs index 9b69850..69966f5 100644 --- a/Mara.Tester/Program.cs +++ b/Mara.Tester/Program.cs @@ -11,17 +11,7 @@ static void Main(string[] args) if (args.Length != 4) PrintInfo(); - // Check ori folder - if (!CheckDirectoryOrFile(args[1], true)) - return; - - // Check result folder - if (!CheckDirectoryOrFile(args[2], true)) - return; - - // Check zip file - if (!CheckDirectoryOrFile(args[3], false)) - return; + CheckPaths(args[1], args[2], args[3], args[0]); switch (args[0].ToUpper()) { @@ -31,6 +21,12 @@ static void Main(string[] args) case "PSVITA": ImportVita(args[1], args[2], args[3]); break; + case "3DS-GENERAL": + Import3dsGeneral(args[1], args[2], args[3]); + break; + case "3DS-SPECIFIC": + Import3dsSpecific(args[1], args[2], args[3]); + break; default: PrintInfo(); break; @@ -50,6 +46,18 @@ private static void ImportPc(string oriFolder, string outFolder, string zipPatch PrintResult(mainVita.ApplyTranslation()); } + private static void Import3dsGeneral(string oriFolder, string outFolder, string zipPatch) + { + var main3DS = new Lib.Platforms._3ds.Main(oriFolder, outFolder, zipPatch, Lib.Platforms._3ds.PatchMode.General); + PrintResult(main3DS.ApplyTranslation()); + } + + private static void Import3dsSpecific(string oriFolder, string outFolder, string zipPatch) + { + var main3DS = new Lib.Platforms._3ds.Main(oriFolder, outFolder, zipPatch, Lib.Platforms._3ds.PatchMode.Specific); + PrintResult(main3DS.ApplyTranslation()); + } + private static void PrintResult((int, string) result) { Console.WriteLine($"RESULT CODE: {result.Item1}\n" + @@ -64,6 +72,33 @@ private static void PrintInfo() Console.WriteLine("Mara.Tester PSVITA \"ORIGINAL FILES FOLDER\" \"OUT PATCHED FILES FOLDER\" \"ZIP DATA PATH\""); } + static void CheckPaths(string oriPath, string outPath, string zipPath, string patchPlatform) + { + bool isDirectory = true; + + switch (patchPlatform.ToUpper()) + { + case "3DS-GENERAL": + isDirectory = false; + break; + case "3DS-SPECIFIC": + isDirectory = false; + break; + } + + // Check ori folder + if (!CheckDirectoryOrFile(oriPath, isDirectory)) + return; + + // Check result folder + if (!CheckDirectoryOrFile(outPath, isDirectory)) + return; + + // Check zip file + if (!CheckDirectoryOrFile(zipPath, false)) + return; + } + private static bool CheckDirectoryOrFile(string path, bool isDirectory) { if (!isDirectory) From dc9e03de88b62ce7654fe2c52e6e3b3357672c82 Mon Sep 17 00:00:00 2001 From: WorstAquaPlayer Date: Sat, 8 Jan 2022 01:06:28 -0300 Subject: [PATCH 6/7] Add support to ExeFS patching in specific mode. Turns out there was an NodeContainer to ExeFS binary converter in Lemon, I just didn't see it. Also, made some small fixes to the tester. --- Mara.Lib/Platforms/3ds/Main.cs | 54 ++++++++++++++++++++++++---------- Mara.Tester/Program.cs | 6 ++-- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/Mara.Lib/Platforms/3ds/Main.cs b/Mara.Lib/Platforms/3ds/Main.cs index 3f36443..4f5458b 100644 --- a/Mara.Lib/Platforms/3ds/Main.cs +++ b/Mara.Lib/Platforms/3ds/Main.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Yarhl.FileFormat; using Yarhl.FileSystem; using Yarhl.IO; @@ -65,9 +66,17 @@ public Main(string oriFile, string outFile, string patchPath, PatchMode patchMod ContentToPatch.Add(splitLine[0], new List { splitLine[1] }); } - if (patchMode == PatchMode.Specific && splitLine[1] != "rom") + if (patchMode == PatchMode.Specific) { - throw new FormatException($"Unsupported specific patching for {splitLine[1]}"); + switch(splitLine[1]) + { + case "rom": + break; + case "system": + break; + default: + throw new FormatException($"Unsupported specific patching for {splitLine[1]}"); + } } } } @@ -121,22 +130,30 @@ public override (int, string) ApplyTranslation() foreach (var node in Navigator.IterateNodes(contentNode)) { - switch(node.Name) + if (contentToPatch.Value.Contains(node.Name)) { - case "rom": - node.TransformWith(); - break; - } - - foreach(var nodeChild in Navigator.IterateNodes(node)) - { - var path = nodeChild.Path.Replace($"/root/content/{contentToPatch.Key}/", "").Replace('/', Path.DirectorySeparatorChar); + switch (node.Name) + { + case "rom": + node.TransformWith(); + break; + case "system": + node.TransformWith(); + break; + default: + continue; + } - // Using node.Stream will return null for some reason - var nodeChildFromRoot = Navigator.SearchNode(Cia, nodeChild.Path); - if (!nodeChildFromRoot.IsContainer) + foreach (var nodeChild in Navigator.IterateNodes(node)) { - nodeChildFromRoot.Stream.WriteTo(tempFolder + Path.DirectorySeparatorChar + contentToPatch.Key + Path.DirectorySeparatorChar + path); + var path = nodeChild.Path.Replace($"/root/content/{contentToPatch.Key}/", "").Replace('/', Path.DirectorySeparatorChar); + + // Using node.Stream will return null for some reason + var nodeChildFromRoot = Navigator.SearchNode(Cia, nodeChild.Path); + if (!nodeChildFromRoot.IsContainer) + { + nodeChildFromRoot.Stream.WriteTo(tempFolder + Path.DirectorySeparatorChar + contentToPatch.Key + Path.DirectorySeparatorChar + path); + } } } } @@ -171,13 +188,18 @@ public override (int, string) ApplyTranslation() foreach (var contentChild in ContentToPatch[contentToPatch.Key]) { var contentChildPath = $"{contentPath}{Path.DirectorySeparatorChar}{contentChild}"; + ContentNode.Children[contentToPatch.Key].Add(NodeFactory.FromDirectory(contentChildPath, "*", contentChild, true)); switch (contentChild) { case "rom": - ContentNode.Children[contentToPatch.Key].Add(NodeFactory.FromDirectory(contentChildPath, "*", contentChild, true)); ContentNode.Children[contentToPatch.Key].Children[contentChild].TransformWith(); break; + case "system": + IConverter binaryConverter = new BinaryExeFs2NodeContainer(); + var convertedNode = binaryConverter.Convert(ContentNode.Children[contentToPatch.Key].Children[contentChild].GetFormatAs()); + ContentNode.Children[contentToPatch.Key].Children[contentChild].ChangeFormat(convertedNode); + break; } } diff --git a/Mara.Tester/Program.cs b/Mara.Tester/Program.cs index 69966f5..3ea410e 100644 --- a/Mara.Tester/Program.cs +++ b/Mara.Tester/Program.cs @@ -80,18 +80,20 @@ static void CheckPaths(string oriPath, string outPath, string zipPath, string pa { case "3DS-GENERAL": isDirectory = false; + outPath = Path.GetDirectoryName(outPath); break; case "3DS-SPECIFIC": isDirectory = false; + outPath = Path.GetDirectoryName(outPath); break; } - // Check ori folder + // Check ori folder/file if (!CheckDirectoryOrFile(oriPath, isDirectory)) return; // Check result folder - if (!CheckDirectoryOrFile(outPath, isDirectory)) + if (!CheckDirectoryOrFile(outPath, true)) return; // Check zip file From 38e4fdacc7bba30fdeaf84402242b672c24d03b0 Mon Sep 17 00:00:00 2001 From: WorstAquaPlayer Date: Thu, 20 Jan 2022 18:06:56 -0300 Subject: [PATCH 7/7] Allow to use only FileStream in ApplyXdelta. Some small fixes to the tester as well. --- Mara.Lib/Common/Xdelta.cs | 13 +++++++++++++ Mara.Lib/Platforms/3ds/Main.cs | 24 ++++++++++++++++++++---- Mara.Lib/Platforms/PatchProcess.cs | 7 +++++-- Mara.Tester/Program.cs | 18 +++++++++++------- 4 files changed, 49 insertions(+), 13 deletions(-) diff --git a/Mara.Lib/Common/Xdelta.cs b/Mara.Lib/Common/Xdelta.cs index d15c6b3..77bd7fa 100644 --- a/Mara.Lib/Common/Xdelta.cs +++ b/Mara.Lib/Common/Xdelta.cs @@ -15,5 +15,18 @@ public static void Apply(FileStream file, byte[] xdeltaFile, string outfile) outStream.Close(); file.Close(); } + + public static void ApplyFileStream(string file, string xdeltaFile, string outfile) + { + using var fileStream = new FileStream(file, FileMode.Open); + using var xdeltaStream = new FileStream(xdeltaFile, FileMode.Open); + using var outStream = new FileStream(outfile, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); + + var decoder = new Decoder(fileStream, xdeltaStream, outStream); + decoder.Run(); + fileStream.Close(); + xdeltaStream.Close(); + outStream.Close(); + } } } diff --git a/Mara.Lib/Platforms/3ds/Main.cs b/Mara.Lib/Platforms/3ds/Main.cs index 4f5458b..a88e12c 100644 --- a/Mara.Lib/Platforms/3ds/Main.cs +++ b/Mara.Lib/Platforms/3ds/Main.cs @@ -15,13 +15,15 @@ namespace Mara.Lib.Platforms._3ds public class Main : PatchProcess { public PatchMode PatchMode { get; set; } + bool UseFileStream { get; set; } Node Cia { get; set; } Node ContentNode { get; set; } Dictionary> ContentToPatch = new Dictionary>(); - public Main(string oriFile, string outFile, string patchPath, PatchMode patchMode) : base(oriFile, outFile, patchPath) + public Main(string oriFile, string outFile, string patchPath, PatchMode patchMode, bool useFileStream = false) : base(oriFile, outFile, patchPath) { PatchMode = patchMode; + UseFileStream = useFileStream; try { @@ -107,7 +109,7 @@ public override (int, string) ApplyTranslation() var file = $"{tempFolder}{Path.DirectorySeparatorChar}{files.ListOriFiles[i]}"; var xdelta = $"{tempFolder}{Path.DirectorySeparatorChar}{files.ListXdeltaFiles[i]}"; - var result = ApplyXdelta(file, xdelta, file, files.ListMd5Files[i]); + var result = ApplyXdelta(file, xdelta, file, files.ListMd5Files[i], UseFileStream); if (result.Item1 != 0) return result; @@ -119,7 +121,14 @@ public override (int, string) ApplyTranslation() foreach (var contentToPatch in ContentToPatch) { var contentChildNode = ContentNode.Children[contentToPatch.Key]; + var contentChildPath = $"{tempFolder}{Path.DirectorySeparatorChar}{contentToPatch.Key}"; contentChildNode.TransformWith(); + + // Doing this reduces the amount of memory used. + Directory.Delete(contentChildPath, true); + contentChildNode.Stream.WriteTo(contentChildPath); + + ContentNode.Add(NodeFactory.FromFile(contentChildPath, contentToPatch.Key)); } break; case PatchMode.Specific: @@ -164,7 +173,7 @@ public override (int, string) ApplyTranslation() var file = $"{tempFolder}{Path.DirectorySeparatorChar}{files.ListOriFiles[i]}"; var xdelta = $"{tempFolder}{Path.DirectorySeparatorChar}{files.ListXdeltaFiles[i]}"; - var result = ApplyXdelta(file, xdelta, file, files.ListMd5Files[i]); + var result = ApplyXdelta(file, xdelta, file, files.ListMd5Files[i], UseFileStream); if (result.Item1 != 0) return result; @@ -183,7 +192,7 @@ public override (int, string) ApplyTranslation() foreach (var contentToPatch in ContentToPatch) { - var contentPath = $"{tempFolder}{Path.DirectorySeparatorChar}{contentToPatch.Key}{Path.DirectorySeparatorChar}"; + var contentPath = $"{tempFolder}{Path.DirectorySeparatorChar}{contentToPatch.Key}"; foreach (var contentChild in ContentToPatch[contentToPatch.Key]) { @@ -204,6 +213,13 @@ public override (int, string) ApplyTranslation() } ContentNode.Children[contentToPatch.Key].TransformWith(); + + // Doing this reduces the amount of memory used. + Directory.Delete(contentPath, true); + ContentNode.Children[contentToPatch.Key].Stream.WriteTo(contentPath); + ContentNode.Children[contentToPatch.Key].Dispose(); + + ContentNode.Add(NodeFactory.FromFile(contentPath, contentToPatch.Key)); } break; } diff --git a/Mara.Lib/Platforms/PatchProcess.cs b/Mara.Lib/Platforms/PatchProcess.cs index 5fa00e6..7a14faa 100644 --- a/Mara.Lib/Platforms/PatchProcess.cs +++ b/Mara.Lib/Platforms/PatchProcess.cs @@ -30,7 +30,7 @@ public virtual (int, string) ApplyTranslation() } - protected (int, string) ApplyXdelta(string file, string xdelta, string result, string md5) + protected (int, string) ApplyXdelta(string file, string xdelta, string result, string md5, bool deltaFileStream = false) { if (!File.Exists(file + "_ori")) File.Move(file, file + "_ori"); @@ -50,7 +50,10 @@ public virtual (int, string) ApplyTranslation() try { - Common.Xdelta.Apply(File.Open(file, FileMode.Open), File.ReadAllBytes(xdelta), result); + if (!deltaFileStream) + Common.Xdelta.Apply(File.Open(file, FileMode.Open), File.ReadAllBytes(xdelta), result); + else + Common.Xdelta.ApplyFileStream(file, xdelta, result); } catch (Exception e) { diff --git a/Mara.Tester/Program.cs b/Mara.Tester/Program.cs index 3ea410e..4db6cc1 100644 --- a/Mara.Tester/Program.cs +++ b/Mara.Tester/Program.cs @@ -46,15 +46,15 @@ private static void ImportPc(string oriFolder, string outFolder, string zipPatch PrintResult(mainVita.ApplyTranslation()); } - private static void Import3dsGeneral(string oriFolder, string outFolder, string zipPatch) + private static void Import3dsGeneral(string oriFile, string outFile, string zipPatch) { - var main3DS = new Lib.Platforms._3ds.Main(oriFolder, outFolder, zipPatch, Lib.Platforms._3ds.PatchMode.General); + var main3DS = new Lib.Platforms._3ds.Main(oriFile, outFile, zipPatch, Lib.Platforms._3ds.PatchMode.General); PrintResult(main3DS.ApplyTranslation()); } - private static void Import3dsSpecific(string oriFolder, string outFolder, string zipPatch) + private static void Import3dsSpecific(string oriFile, string outFile, string zipPatch) { - var main3DS = new Lib.Platforms._3ds.Main(oriFolder, outFolder, zipPatch, Lib.Platforms._3ds.PatchMode.Specific); + var main3DS = new Lib.Platforms._3ds.Main(oriFile, outFile, zipPatch, Lib.Platforms._3ds.PatchMode.Specific); PrintResult(main3DS.ApplyTranslation()); } @@ -93,7 +93,7 @@ static void CheckPaths(string oriPath, string outPath, string zipPath, string pa return; // Check result folder - if (!CheckDirectoryOrFile(outPath, true)) + if (!CheckDirectoryOrFile(outPath, true, true)) return; // Check zip file @@ -101,9 +101,9 @@ static void CheckPaths(string oriPath, string outPath, string zipPath, string pa return; } - private static bool CheckDirectoryOrFile(string path, bool isDirectory) + private static bool CheckDirectoryOrFile(string path, bool isDirectory, bool isOut = false) { - if (!isDirectory) + if (!isDirectory && !isOut) { if (File.Exists(path)) return true; @@ -112,6 +112,10 @@ private static bool CheckDirectoryOrFile(string path, bool isDirectory) return false; } + else if (!isDirectory && isOut) + { + path = Path.GetDirectoryName(path); + } if (Directory.Exists(path)) return true;