0
mirror of https://github.com/sampletext32/ParkanPlayground.git synced 2025-07-01 04:40:25 +03:00
Files
ParkanPlayground/NResLib/NResPacker.cs
2025-06-22 18:47:21 +03:00

151 lines
5.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Buffers.Binary;
using System.Text;
namespace NResLib;
public class NResPacker
{
public static string Pack(NResArchive archive, string srcNresPath, string contentDirectoryPath, string targetFileDirectoryPath)
{
var diskFiles = Directory.GetFiles(contentDirectoryPath)
.Select(Path.GetFileName)
.ToList();
var fileOffset = 16; // 16 по умолчанию, т.к. есть заголовок в 16 байт.
var metadataItems = new List<ListMetadataItem>();
foreach (var archiveFile in archive.Files)
{
var extension = Path.GetExtension(archiveFile.FileName);
var fileName = Path.GetFileNameWithoutExtension(archiveFile.FileName);
if (extension == "")
{
extension = ".bin";
}
var targetFileName = $"{archiveFile.Index}_{archiveFile.FileType}_{fileName}{extension}";
if (diskFiles.All(x => x != targetFileName))
{
return $"Не найдён файл {targetFileName}";
}
var filePath = Path.Combine(contentDirectoryPath, targetFileName);
var fileInfo = new FileInfo(filePath);
if (!fileInfo.Exists)
{
throw new Exception();
}
var newFileLength = (int)fileInfo.Length;
var listItem = new ListMetadataItem(
archiveFile.FileType,
archiveFile.ElementCount,
archiveFile.Magic1,
newFileLength,
archiveFile.ElementSize,
archiveFile.FileName,
archiveFile.Magic3,
archiveFile.Magic4,
archiveFile.Magic5,
archiveFile.Magic6,
fileOffset,
archiveFile.Index
);
fileOffset += newFileLength;
metadataItems.Add(listItem);
}
var totalFileLength =
16 + // заголовок
metadataItems.Sum(x => x.FileLength) + // сумма длин всех файлов
metadataItems.Count * 64; // длина всех метаданных
var header = new NResArchiveHeader(archive.Header.NRes, archive.Header.Version, archive.Header.FileCount, totalFileLength);
var targetArchive = new NResArchive(header, metadataItems);
// имя архива = имени папки в которую архив распаковывали
string targetArchiveFileName = Path.GetFileName(srcNresPath)!;
var targetArchivePath = Path.Combine(targetFileDirectoryPath, targetArchiveFileName);
using var fs = new FileStream(targetArchivePath, FileMode.CreateNew);
Span<byte> span = stackalloc byte[4];
span.Clear();
Encoding.ASCII.GetBytes(header.NRes, span);
fs.Write(span);
BinaryPrimitives.WriteInt32LittleEndian(span, header.Version);
fs.Write(span);
BinaryPrimitives.WriteInt32LittleEndian(span, header.FileCount);
fs.Write(span);
BinaryPrimitives.WriteInt32LittleEndian(span, header.TotalFileLengthBytes);
fs.Write(span);
foreach (var archiveFile in targetArchive.Files)
{
var extension = Path.GetExtension(archiveFile.FileName);
var fileName = Path.GetFileNameWithoutExtension(archiveFile.FileName);
if (extension == "")
{
extension = ".bin";
}
var targetFileName = $"{archiveFile.Index}_{archiveFile.FileType}_{fileName}{extension}";
var filePath = Path.Combine(contentDirectoryPath, targetFileName);
using var srcFs = new FileStream(filePath, FileMode.Open);
srcFs.CopyTo(fs);
}
Span<byte> fileNameSpan = stackalloc byte[20];
foreach (var archiveFile in targetArchive.Files)
{
span.Clear();
Encoding.ASCII.GetBytes(archiveFile.FileType, span);
fs.Write(span);
BinaryPrimitives.WriteUInt32LittleEndian(span, archiveFile.ElementCount);
fs.Write(span);
BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.Magic1);
fs.Write(span);
BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.FileLength);
fs.Write(span);
BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.ElementSize);
fs.Write(span);
fileNameSpan.Clear();
Encoding.ASCII.GetBytes(archiveFile.FileName, fileNameSpan);
fs.Write(fileNameSpan);
BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.Magic3);
fs.Write(span);
BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.Magic4);
fs.Write(span);
BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.Magic5);
fs.Write(span);
BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.Magic6);
fs.Write(span);
BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.OffsetInFile);
fs.Write(span);
BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.Index);
fs.Write(span);
}
fs.Flush();
return "Запакован архив";
}
}