cxml-decompiler/AppInfoCli/AppInfo.cs

301 lines
8.5 KiB
C#
Raw Normal View History

2019-04-27 14:43:27 +00:00
using System;
using System.Drawing;
using System.IO;
using System.Text;
namespace AppInfo
{
class Types
{
public static int TYPE_TEXT = 0;
public static int TYPE_PNG = 1;
}
class Tools
{
public static MemoryStream ByteToStream(byte[] Array)
{
MemoryStream ms = new MemoryStream();
ms.Write(Array, 0x00, Array.Length);
ms.Seek(0, SeekOrigin.Begin);
return ms;
}
public static Bitmap GetBitmap(byte[] BitmapBytes)
{
MemoryStream ms = ByteToStream(BitmapBytes);
Bitmap bmp = new Bitmap(ms);
ms.Dispose();
return bmp;
}
public static int GetType(byte[] FileData)
{
try
{
MemoryStream ms = ByteToStream(FileData);
Bitmap bmp = new Bitmap(ms);
bmp.Dispose();
ms.Dispose();
return Types.TYPE_PNG;
}
catch(Exception)
{
return Types.TYPE_TEXT;
}
}
}
class Parser
{
private static byte[] _getImageOfSize(int width, int height)
{
int max = GetFileCount();
for (int i = 0; i <= max; i++)
{
byte[] FileData = GetFile(i);
if (Tools.GetType(FileData) == Types.TYPE_PNG)
{
Bitmap bmp = Tools.GetBitmap(FileData);
if (bmp.Width == width && bmp.Height == height)
{
return FileData;
}
}
}
throw new FileNotFoundException();
}
private static bool _checkMagicNumber()
{
if (StringRepresentation.StartsWith("PSMA"))
{
return true;
}
else
{
return false;
}
}
private static int _readInt32At(int offset)
{
InfoFile.Seek(offset, SeekOrigin.Begin);
BinaryReader BinReader = new BinaryReader(InfoFile);
int int32 = BinReader.ReadInt32();
return int32;
}
static FileStream InfoFile;
static String StringRepresentation;
public static void Init(string Path)
{
StringRepresentation = Encoding.ASCII.GetString(File.ReadAllBytes(Path));
InfoFile = File.Open(Path, FileMode.Open, FileAccess.Read);
if(!_checkMagicNumber())
{
throw new Exception("Incorrect magic number.");
}
return;
}
public static int GetTableOffset()
{
return _readInt32At(0x8);
}
public static int GetTableSize()
{
return _readInt32At(0xC);
}
public static int GetFileTableOffset()
{
return _readInt32At(0x48);
}
public static int GetFileTableSize()
{
return _readInt32At(0x4C);
}
public static int GetStringTableOffset()
{
return _readInt32At(0x20);
}
public static int GetStringTableSize()
{
return _readInt32At(0x24);
}
public static byte[] GetStringTable()
{
int StringTableOffset = GetStringTableOffset();
int StringTableSize = GetStringTableSize();
InfoFile.Seek(StringTableOffset, SeekOrigin.Begin);
byte[] StringTable = new byte[StringTableSize];
InfoFile.Read(StringTable, 0x00, StringTableSize);
return StringTable;
}
public static byte[] GetTable()
{
int TableOffset = GetTableOffset();
int TableSize = GetTableSize();
InfoFile.Seek(TableOffset, SeekOrigin.Begin);
byte[] Table = new byte[TableSize];
InfoFile.Read(Table, 0x00, TableSize);
return Table;
}
public static byte[] GetFileTable()
{
int DataOffset = GetFileTableOffset();
int DataLength = GetFileTableSize();
InfoFile.Seek(DataOffset, SeekOrigin.Begin);
byte[] FileTable = new byte[DataLength];
InfoFile.Read(FileTable, 0x00, DataLength);
return FileTable;
}
public static int GetFileCount()
{
int i = 0;
while(true)
{
try
{
GetFile(i);
i++;
}
catch(Exception)
{
return i - 1;
}
}
}
public static byte[] GetBackground()
{
return _getImageOfSize(854, 480);
}
public static byte[] GetIcon128()
{
return _getImageOfSize(128, 128);
}
public static byte[] GetIcon256()
{
return _getImageOfSize(256, 256);
}
public static byte[] GetIcon512()
{
return _getImageOfSize(512, 512);
}
public static byte[] GetCopyright()
{
int max = GetFileCount();
for (int i = 0; i <= max; i++)
{
byte[] FileData = GetFile(i);
if (Tools.GetType(FileData) == Types.TYPE_TEXT)
{
return FileData;
}
}
throw new FileNotFoundException();
}
public static String GetProperty(String key)
{
String[] StringTableArray = Encoding.UTF8.GetString(GetStringTable()).Split('\x00');
int index = Array.IndexOf(StringTableArray, key);
return StringTableArray[index + 1];
}
public static byte[] GetFile(int FileIndex)
{
int DataOffset = GetFileTableOffset();
int DataLength = GetFileTableSize();
int TableOffset = GetTableOffset();
//This is a bit of a hack. but i couldnt work out the real format.
int FirstPngSize = (StringRepresentation.IndexOf("IEND") + 8) - DataOffset;
MemoryStream MemStream = Tools.ByteToStream(GetTable());
BinaryReader BinReader = new BinaryReader(MemStream);
while (BinReader.ReadInt32() != FirstPngSize) { };
MemStream.Seek(-8, SeekOrigin.Current);
MemoryStream FileTableStream = Tools.ByteToStream(GetFileTable());
int FileStart = 0;
int FileSize = 0;
for (int i = 0; i <= FileIndex; i += 1)
{
FileStart = BinReader.ReadInt32();
FileSize = BinReader.ReadInt32();
MemStream.Seek(0x8, SeekOrigin.Current);
if (i != 0 && FileStart == 0)
{
MemStream.Seek(-32, SeekOrigin.Current);
FileStart = BinReader.ReadInt32();
FileSize = BinReader.ReadInt32();
FileStart += FileSize;
FileSize = DataLength - FileStart;
if(FileIndex > i)
{
throw new FileNotFoundException();
}
}
}
byte[] FileData = new byte[FileSize];
FileTableStream.Seek(FileStart, SeekOrigin.Begin);
FileTableStream.Read(FileData, 0, FileSize);
if(Tools.GetType(FileData) == Types.TYPE_TEXT)
{
String CopyrightData = Encoding.UTF8.GetString(FileData);
CopyrightData = CopyrightData.Replace("\x00", "");
FileData = Encoding.UTF8.GetBytes(CopyrightData);
}
return FileData;
}
public static String[] GetInfoTable()
{
BinaryReader BinReader = new BinaryReader(InfoFile);
InfoFile.Seek(0x20, SeekOrigin.Begin);
int InfoTableOffset = BinReader.ReadInt32();
int InfoLength = BinReader.ReadInt32();
InfoFile.Seek(InfoTableOffset, SeekOrigin.Begin);
byte[] InfoTable = new byte[InfoLength];
InfoFile.Read(InfoTable, 0, InfoLength);
String Files = Encoding.UTF8.GetString(InfoTable);
String[] FileList = Files.Split('\x00');
foreach(String file in FileList)
{
Console.WriteLine(file);
}
return FileList;
}
}
}