Template
*
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30011.22
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Packer", "Packer.csproj", "{AD9FC833-6014-4F84-A856-9376B189B4EA}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{AD9FC833-6014-4F84-A856-9376B189B4EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AD9FC833-6014-4F84-A856-9376B189B4EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AD9FC833-6014-4F84-A856-9376B189B4EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AD9FC833-6014-4F84-A856-9376B189B4EA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {6AC09086-6342-4C65-A967-707E51E76482}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,184 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Packer{
|
||||
class Program{
|
||||
|
||||
static readonly List<Extensions> extensions = new List<Extensions>(
|
||||
new Extensions[] {
|
||||
new Extensions { Source = ".mmm", Destination = ".mad" },
|
||||
new Extensions { Source = ".mtm", Destination = ".mtd" },
|
||||
new Extensions { Source = ".pmm", Destination = ".pmg" },
|
||||
new Extensions { Source = ".pom", Destination = ".pog" },
|
||||
new Extensions { Source = ".ptm", Destination = ".ptg" }
|
||||
});
|
||||
|
||||
|
||||
static byte[] Decompress(byte[] source) {
|
||||
int offset = 0;
|
||||
|
||||
List<byte> outBuffer = new List<byte>();
|
||||
|
||||
|
||||
|
||||
while (source[offset] != 0) {
|
||||
byte blockType = source[offset];
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
while (source[offset] != 0) {
|
||||
byte blockType = source[offset];
|
||||
|
||||
if (blockType < 0x40) {
|
||||
outBuffer.AddRange(source.AsSpan(offset + 1, blockType).ToArray());
|
||||
offset += 1 + blockType;
|
||||
} else if (blockType < 0x50) {
|
||||
var count = (blockType - 0x40) + 3;
|
||||
|
||||
byte v0 = outBuffer[outBuffer.Count - 2];
|
||||
byte v1 = outBuffer[outBuffer.Count - 1];
|
||||
|
||||
//byte v0 = source[offset - 2];
|
||||
//byte v1 = source[offset - 1];
|
||||
|
||||
v0 = (byte)(v1 - v0);
|
||||
do {
|
||||
v1 += v0;
|
||||
outBuffer.Add(v1);
|
||||
--count;
|
||||
}
|
||||
while (count != 0);
|
||||
|
||||
offset += 1;
|
||||
|
||||
} else if (blockType < 0x60) {
|
||||
var count = (blockType - 0x50) + 2;
|
||||
|
||||
short v0 = (short)(outBuffer[outBuffer.Count - 4] | ((short)outBuffer[outBuffer.Count - 3] << 8));
|
||||
short v1 = (short)(outBuffer[outBuffer.Count - 2] | ((short)outBuffer[outBuffer.Count - 1] << 8));
|
||||
|
||||
//short v0 = (short)(source[offset - 4] | ((short)source[offset - 3] << 8));
|
||||
//short v1 = (short)(source[offset - 2] | ((short)source[offset - 1] << 8));
|
||||
|
||||
v0 = (short)(v1 - v0);
|
||||
do {
|
||||
v1 += v0;
|
||||
outBuffer.Add((byte)(v1 & 0xff));
|
||||
outBuffer.Add((byte)((v1 >> 8) & 0xff));
|
||||
--count;
|
||||
}
|
||||
while (count != 0);
|
||||
|
||||
offset += 1;
|
||||
} else if (blockType < 0x70) { //Copy last written byte (base 3)
|
||||
var b = outBuffer[outBuffer.Count - 1];
|
||||
var copyCount = (blockType - 0x60) + 3;
|
||||
for (int i = 0; i < copyCount; ++i) {
|
||||
outBuffer.Add(b);
|
||||
}
|
||||
offset += 1;
|
||||
} else if (blockType < 0x80) {
|
||||
var b0 = outBuffer[outBuffer.Count - 2];
|
||||
var b1 = outBuffer[outBuffer.Count - 1];
|
||||
|
||||
var copyCount = (blockType - 0x70) + 2;
|
||||
for (int i = 0; i < copyCount; ++i) {
|
||||
outBuffer.Add(b0);
|
||||
outBuffer.Add(b1);
|
||||
}
|
||||
offset += 1;
|
||||
} else if (blockType < 0xC0) { //Copy 3 bytes
|
||||
var backOffset = (blockType - 0x80) + 3;
|
||||
var readOffset = (outBuffer.Count) - backOffset;
|
||||
outBuffer.Add(outBuffer[readOffset + 0]);
|
||||
outBuffer.Add(outBuffer[readOffset + 1]);
|
||||
outBuffer.Add(outBuffer[readOffset + 2]);
|
||||
offset += 1;
|
||||
} else if (blockType < 0xE0) {
|
||||
|
||||
var copyCount = ((blockType - 0xC0) >> 2) + 4;
|
||||
var backOffset = ((blockType - 0xC0) & 3) << 8;
|
||||
|
||||
backOffset += (source[offset + 1] + 3);
|
||||
|
||||
var readStart = (outBuffer.Count) - backOffset;
|
||||
|
||||
|
||||
var block = outBuffer.ToArray().AsSpan(readStart, Math.Min(copyCount, backOffset));
|
||||
|
||||
for(int i = 0; i < copyCount; ++i) {
|
||||
outBuffer.Add(block[i % block.Length]);
|
||||
}
|
||||
|
||||
offset += 2;
|
||||
} else {
|
||||
var backOffset = ((blockType - 0xE0) * 256) + (source[offset + 1] + 3);
|
||||
var bytesCount = source[offset + 2] + 5;
|
||||
var readStart = (outBuffer.Count) - backOffset;
|
||||
for (int i = 0; i < bytesCount; ++i) {
|
||||
outBuffer.Add(outBuffer[readStart + (i % backOffset)]);
|
||||
}
|
||||
offset += 3;
|
||||
}
|
||||
}
|
||||
return outBuffer.ToArray();
|
||||
}
|
||||
|
||||
static void DecompressFile(string input, string output) {
|
||||
var bytes = File.ReadAllBytes(input);
|
||||
var decompressed = Decompress(bytes);
|
||||
File.WriteAllBytes(output, decompressed);
|
||||
}
|
||||
|
||||
struct Extensions {
|
||||
public string Source;
|
||||
public string Destination;
|
||||
}
|
||||
|
||||
static void DecompressDirectory(string directory) {
|
||||
var files = Directory.GetFiles(directory);
|
||||
files = files.Where(v => extensions.Any( g=> g.Source == Path.GetExtension(v).ToLower())).ToArray();
|
||||
|
||||
foreach(var file in files) {
|
||||
var referenceFilePath = Path.GetDirectoryName(file);
|
||||
referenceFilePath = Path.Combine(referenceFilePath, "Decompressed",
|
||||
Path.GetFileNameWithoutExtension(file) + extensions.First(v => v.Source == Path.GetExtension(file).ToLower()).Destination);
|
||||
|
||||
if (!File.Exists(referenceFilePath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var compressedData = File.ReadAllBytes(file);
|
||||
var referenceData = File.ReadAllBytes(referenceFilePath);
|
||||
|
||||
var decompressedData = Decompress(compressedData);
|
||||
|
||||
|
||||
|
||||
var equal = decompressedData.SequenceEqual(referenceData);
|
||||
if (!equal) {
|
||||
throw new Exception("Invalid bytes :(");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
static void Main(string[] args) {
|
||||
string input = @"C:\Users\l-pro\Downloads\!HOW\COLD1.PMM";
|
||||
string output = @"C:\Users\l-pro\Downloads\!HOW\COLD1.PMM_UNK";
|
||||
|
||||
DecompressFile(input, output);
|
||||
|
||||
DecompressDirectory(@"C:\Users\l-pro\Downloads\!HOW\Test");
|
||||
|
||||
Console.WriteLine("Done");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user