This commit is contained in:
2025-05-13 03:10:33 +03:00
parent 5f03062f42
commit e5e3172b0f
80 changed files with 9655 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
</Project>
+25
View File
@@ -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
+184
View File
@@ -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");
}
}
}