pkNX/pkNX.WinForms/Ripper/FileRipper.cs
2024-03-04 20:19:09 -06:00

123 lines
3.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using pkNX.Containers;
namespace pkNX.WinForms;
public enum RipResultCode
{
UnknownFormat,
Success,
FileExist,
BadSize,
ReadError,
}
public static class FileRipper
{
public static ContainerHandler DefaultHandler { private get; set; } = new();
public static readonly List<Func<BinaryReader, uint, string, ContainerHandler, FileRipperResult>> Loaders =
[
GFPackDump,
NSODump,
];
private static FileRipperResult NSODump(BinaryReader br, uint header, string path, ContainerHandler handler)
{
if (header != NSOHeader.ExpectedMagic)
return new FileRipperResult(RipResultCode.UnknownFormat);
br.BaseStream.Position = 0;
var nso = new NSO(br);
var dir = Path.GetDirectoryName(path);
if (dir == null)
return new FileRipperResult(RipResultCode.FileExist);
var folder = Path.GetFileNameWithoutExtension(path);
var resultPath = Path.Combine(dir, folder);
if (resultPath == path)
resultPath += "_nso";
Directory.CreateDirectory(resultPath);
File.WriteAllBytes(Path.Combine(resultPath, "text.bin"), nso.DecompressedText);
File.WriteAllBytes(Path.Combine(resultPath, "data.bin"), nso.DecompressedData);
File.WriteAllBytes(Path.Combine(resultPath, "ro.bin"), nso.DecompressedRO);
return new FileRipperResult(RipResultCode.Success) { ResultPath = resultPath };
}
private static FileRipperResult GFPackDump(BinaryReader br, uint header, string path, ContainerHandler handler)
{
if (header != 0x584C_4647)
return new FileRipperResult(RipResultCode.UnknownFormat);
br.BaseStream.Position = 0;
var gfp = new GFPack(br);
var dir = Path.GetDirectoryName(path);
if (dir == null)
return new FileRipperResult(RipResultCode.FileExist);
var folder = Path.GetFileNameWithoutExtension(path);
var resultPath = Path.Combine(dir, folder);
Directory.CreateDirectory(resultPath);
gfp.Dump(resultPath, handler);
return new FileRipperResult(RipResultCode.Success) {ResultPath = resultPath};
}
public static FileRipperResult TryOpenFile(string path, ContainerHandler? handler = null)
{
if (!File.Exists(path))
return new FileRipperResult(RipResultCode.FileExist);
handler ??= DefaultHandler;
try
{
using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
using var br = new BinaryReader(fs);
if (br.BaseStream.Length < 4)
return new FileRipperResult(RipResultCode.BadSize);
var header = br.ReadUInt32();
var result = TryLoadFile(br, header, path, handler);
if (result.Code == RipResultCode.Success)
return result;
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
return new FileRipperResult(RipResultCode.ReadError);
}
return new FileRipperResult(RipResultCode.UnknownFormat);
}
private static FileRipperResult TryLoadFile(BinaryReader br, uint header, string path, ContainerHandler handler)
{
foreach (var method in Loaders)
{
try
{
var result = method(br, header, path, handler);
if (result.Code == RipResultCode.Success)
return result;
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
}
return new FileRipperResult(RipResultCode.UnknownFormat);
}
}
public class FileRipperResult(RipResultCode code)
{
public readonly RipResultCode Code = code;
public string? ResultPath;
}