mirror of
https://github.com/kwsch/pkNX.git
synced 2026-05-02 10:55:18 -05:00
123 lines
3.8 KiB
C#
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;
|
|
}
|