301 lines
8.5 KiB
C#
301 lines
8.5 KiB
C#
|
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;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|