mirror of
				https://github.com/sampletext32/ParkanPlayground.git
				synced 2025-11-04 07:19:45 +03:00 
			
		
		
		
	Allow to view cp .dat in UI
This commit is contained in:
		
							
								
								
									
										12
									
								
								CpDatLib/CpDatEntry.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								CpDatLib/CpDatEntry.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
namespace CpDatLib;
 | 
			
		||||
 | 
			
		||||
public record CpDatEntry(
 | 
			
		||||
    string ArchiveFile,
 | 
			
		||||
    string ArchiveEntryName,
 | 
			
		||||
    int Magic1,
 | 
			
		||||
    int Magic2,
 | 
			
		||||
    string Description,
 | 
			
		||||
    int Magic3,
 | 
			
		||||
    int ChildCount, // игра не хранит это число в объекте, но оно есть в файле
 | 
			
		||||
    List<CpDatEntry> Children
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										5
									
								
								CpDatLib/CpDatLib.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								CpDatLib/CpDatLib.csproj
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
<Project Sdk="Microsoft.NET.Sdk">
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ProjectReference Include="..\Common\Common.csproj" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
</Project>
 | 
			
		||||
							
								
								
									
										3
									
								
								CpDatLib/CpDatParseResult.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								CpDatLib/CpDatParseResult.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
namespace CpDatLib;
 | 
			
		||||
 | 
			
		||||
public record CpDatParseResult(CpDatScheme? Scheme, string? Error);
 | 
			
		||||
							
								
								
									
										68
									
								
								CpDatLib/CpDatParser.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								CpDatLib/CpDatParser.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
using Common;
 | 
			
		||||
 | 
			
		||||
namespace CpDatLib;
 | 
			
		||||
 | 
			
		||||
public class CpDatParser
 | 
			
		||||
{
 | 
			
		||||
    public static CpDatParseResult Parse(string filePath)
 | 
			
		||||
    {
 | 
			
		||||
        Span<byte> f0f1 = stackalloc byte[4];
 | 
			
		||||
        
 | 
			
		||||
        using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
 | 
			
		||||
 | 
			
		||||
        if (fs.Length < 8)
 | 
			
		||||
            return new CpDatParseResult(null, "File too small to be a valid \"cp\" .dat file.");
 | 
			
		||||
 | 
			
		||||
        fs.ReadExactly(f0f1);
 | 
			
		||||
        
 | 
			
		||||
        if (f0f1[0] != 0xf1 || f0f1[1] != 0xf0)
 | 
			
		||||
        {
 | 
			
		||||
            return new CpDatParseResult(null, "File does not start with expected header bytes f1_f0");
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        var schemeType = (SchemeType)fs.ReadInt32LittleEndian();
 | 
			
		||||
 | 
			
		||||
        var entryLength = 0x6c + 4; // нам нужно прочитать 0x6c (108) байт - это root, и ещё 4 байта - кол-во вложенных объектов
 | 
			
		||||
        if ((fs.Length - 8) % entryLength != 0)
 | 
			
		||||
        {
 | 
			
		||||
            return new CpDatParseResult(null, "File size is not valid according to expected entry length.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        CpDatEntry root = ReadEntryRecursive(fs);
 | 
			
		||||
 | 
			
		||||
        var scheme = new CpDatScheme(schemeType, root);
 | 
			
		||||
 | 
			
		||||
        return new CpDatParseResult(scheme, null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static CpDatEntry ReadEntryRecursive(FileStream fs)
 | 
			
		||||
    {
 | 
			
		||||
        var str1 = fs.ReadNullTerminatedString();
 | 
			
		||||
 | 
			
		||||
        fs.Seek(32 - str1.Length - 1, SeekOrigin.Current); // -1 ignore null terminator
 | 
			
		||||
 | 
			
		||||
        var str2 = fs.ReadNullTerminatedString();
 | 
			
		||||
 | 
			
		||||
        fs.Seek(32 - str2.Length - 1, SeekOrigin.Current); // -1 ignore null terminator
 | 
			
		||||
        var magic1 = fs.ReadInt32LittleEndian();
 | 
			
		||||
        var magic2 = fs.ReadInt32LittleEndian();
 | 
			
		||||
 | 
			
		||||
        var descriptionString = fs.ReadNullTerminatedString();
 | 
			
		||||
 | 
			
		||||
        fs.Seek(32 - descriptionString.Length - 1, SeekOrigin.Current); // -1 ignore null terminator
 | 
			
		||||
        var magic3 = fs.ReadInt32LittleEndian();
 | 
			
		||||
 | 
			
		||||
        // игра не читает количество внутрь схемы, вместо этого она сразу рекурсией читает нужно количество вложенных объектов
 | 
			
		||||
        var childCount = fs.ReadInt32LittleEndian();
 | 
			
		||||
        
 | 
			
		||||
        List<CpDatEntry> children = new List<CpDatEntry>(childCount);
 | 
			
		||||
        
 | 
			
		||||
        for (var i = 0; i < childCount; i++)
 | 
			
		||||
        {
 | 
			
		||||
            var child = ReadEntryRecursive(fs);
 | 
			
		||||
            children.Add(child);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return new CpDatEntry(str1, str2, magic1, magic2, descriptionString, magic3, childCount, Children: children);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								CpDatLib/CpDatScheme.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								CpDatLib/CpDatScheme.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
namespace CpDatLib;
 | 
			
		||||
 | 
			
		||||
public record CpDatScheme(SchemeType Type, CpDatEntry Root);
 | 
			
		||||
							
								
								
									
										29
									
								
								CpDatLib/CpEntryType.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								CpDatLib/CpEntryType.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
namespace CpDatLib;
 | 
			
		||||
 | 
			
		||||
public enum SchemeType : uint
 | 
			
		||||
{
 | 
			
		||||
    ClassBuilding = 0x80000000,
 | 
			
		||||
    ClassRobot = 0x01000000,
 | 
			
		||||
    ClassAnimal = 0x20000000,
 | 
			
		||||
 | 
			
		||||
    BunkerSmall = 0x80010000,
 | 
			
		||||
    BunkerMedium = 0x80020000,
 | 
			
		||||
    BunkerLarge = 0x80040000,
 | 
			
		||||
    Generator = 0x80000002,
 | 
			
		||||
    Mine = 0x80000004,
 | 
			
		||||
    Storage = 0x80000008,
 | 
			
		||||
    Plant = 0x80000010,
 | 
			
		||||
    Hangar = 0x80000040,
 | 
			
		||||
    TowerMedium = 0x80100000,
 | 
			
		||||
    TowerLarge = 0x80200000,
 | 
			
		||||
    MainTeleport = 0x80000200,
 | 
			
		||||
    Institute = 0x80000400,
 | 
			
		||||
    Bridge = 0x80001000,
 | 
			
		||||
    Ruine = 0x80002000,
 | 
			
		||||
 | 
			
		||||
    RobotTransport = 0x01002000,
 | 
			
		||||
    RobotBuilder = 0x01004000,
 | 
			
		||||
    RobotBattleunit = 0x01008000,
 | 
			
		||||
    RobotHq = 0x01010000,
 | 
			
		||||
    RobotHero = 0x01020000,
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user