diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..b978576 --- /dev/null +++ b/Program.cs @@ -0,0 +1,86 @@ +//Written for games in the Spiller Engine, by Ratalaika Games. https://ratalaikagames.com/ +//The Minotaur https://store.steampowered.com/app/412540/ +//Defend Your Crypt https://store.steampowered.com/app/457450/ +//League of Evil https://store.steampowered.com/app/491060/ +//Squareboy vs Bullies Arena Edition https://store.steampowered.com/app/709620/ +using System; +using System.IO; +using System.IO.Compression; + +namespace Ratalaika_Games_Spiller_Engine_Extractor +{ + class Program + { + public static BinaryReader br; + + private static void Main(string[] args) + { + br = new BinaryReader(File.OpenRead(args[0])); + br.ReadChars(15);//"Ratalaika Games" + br.BaseStream.Position = 32; + int ZLibSize = br.ReadInt32(); + int unknown1 = br.ReadInt32(); + int unknown2 = br.ReadInt32(); + int unknown3 = br.ReadInt32(); + Directory.CreateDirectory(Path.GetDirectoryName(args[0]) + "\\" + Path.GetFileNameWithoutExtension(args[0])); + + MemoryStream fileData = new(); + br.ReadInt16(); + using (var ds = new DeflateStream(new MemoryStream(br.ReadBytes(ZLibSize - 2)), CompressionMode.Decompress)) + ds.CopyTo(fileData); + + ZLibSize = br.ReadInt32(); + int DecompressedSize = br.ReadInt32(); + + MemoryStream fileTable = new(); + br.ReadInt16(); + using (var ds = new DeflateStream(new MemoryStream(br.ReadBytes(ZLibSize - 2)), CompressionMode.Decompress)) + ds.CopyTo(fileTable); + br.Close(); + + br = new(fileTable); + br.BaseStream.Position = 0; + System.Collections.Generic.List table = new(); + while (br.BaseStream.Position < br.BaseStream.Length) + table.Add(new()); + br.Close(); + + br = new(fileData); + foreach(FileTableEntry file in table) + { + br.BaseStream.Position = file.end - file.Size; + Directory.CreateDirectory(Path.GetDirectoryName(args[0]) + "//" + Path.GetFileNameWithoutExtension(args[0]) + "//" + Path.GetDirectoryName(file.name)); + using FileStream FS = File.Create(Path.GetDirectoryName(args[0]) + "//" + Path.GetFileNameWithoutExtension(args[0]) + "//" + file.name); + BinaryWriter bw = new(FS); + bw.Write(br.ReadBytes(file.Size)); + bw.Close(); + } + br.Close(); + } + + class FileTableEntry + { + public readonly string name = NullTerminatedString(); + public readonly int Size = br.ReadInt32(); + public readonly int end = br.ReadInt32(); + readonly int unknown1 = br.ReadInt32(); + readonly int unknown2 = br.ReadInt32(); + readonly int unknown3 = br.ReadInt32(); + } + + public static string NullTerminatedString() + { + char[] fileName = Array.Empty(); + char readchar = (char)1; + while (readchar > 0) + { + readchar = br.ReadChar(); + Array.Resize(ref fileName, fileName.Length + 1); + fileName[^1] = readchar; + } + Array.Resize(ref fileName, fileName.Length - 1); + string name = new(fileName); + return name; + } + } +} diff --git a/Ratalaika-Games-Spiller-Engine-Extractor.csproj b/Ratalaika-Games-Spiller-Engine-Extractor.csproj new file mode 100644 index 0000000..4a9290b --- /dev/null +++ b/Ratalaika-Games-Spiller-Engine-Extractor.csproj @@ -0,0 +1,9 @@ + + + + Exe + net5.0 + Ratalaika_Games_Spiller_Engine_Extractor + + + diff --git a/Ratalaika-Games-Spiller-Engine-Extractor.sln b/Ratalaika-Games-Spiller-Engine-Extractor.sln new file mode 100644 index 0000000..cae2aa6 --- /dev/null +++ b/Ratalaika-Games-Spiller-Engine-Extractor.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.34407.143 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ratalaika-Games-Spiller-Engine-Extractor", "Ratalaika-Games-Spiller-Engine-Extractor.csproj", "{EF5AA135-3FF8-4085-B277-838065EEAE7E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EF5AA135-3FF8-4085-B277-838065EEAE7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF5AA135-3FF8-4085-B277-838065EEAE7E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF5AA135-3FF8-4085-B277-838065EEAE7E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF5AA135-3FF8-4085-B277-838065EEAE7E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9EB5867A-6F8E-4EE5-823F-817013937DA2} + EndGlobalSection +EndGlobal