Add resource decoders for all GEM resources but the color icon.

This commit is contained in:
2018-02-27 20:21:27 +00:00
parent 6cec04d72f
commit 396f982600
6 changed files with 484 additions and 55 deletions

View File

@@ -27,7 +27,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using libexeinfo;
@@ -121,48 +121,88 @@ namespace exeinfo
foreach(NE.ResidentName name in ((NE)neExe).NonResidentNames)
Console.WriteLine("\t\t{0} at index {1}", name.name, name.entryTableIndex);
}
if(neExe.Strings != null && neExe.Strings.Any())
{
Console.WriteLine("\tStrings:");
foreach(string str in neExe.Strings) Console.WriteLine("\t\t{0}", str);
}
}
else if(lxExe.Recognized)
{
recognized = true;
Console.Write(lxExe.Information);
if(lxExe.Strings != null && lxExe.Strings.Any())
{
Console.WriteLine("\tStrings:");
foreach(string str in lxExe.Strings) Console.WriteLine("\t\t{0}", str);
}
}
else if(peExe.Recognized)
{
recognized = true;
Console.Write(peExe.Information);
if(peExe.Strings != null && peExe.Strings.Any())
{
Console.WriteLine("\tStrings:");
foreach(string str in peExe.Strings) Console.WriteLine("\t\t{0}", str);
}
}
else if(mzExe.Recognized)
{
recognized = true;
Console.Write(mzExe.Information);
if(mzExe.Strings != null && mzExe.Strings.Any())
{
Console.WriteLine("\tStrings:");
foreach(string str in mzExe.Strings) Console.WriteLine("\t\t{0}", str);
}
}
if(stExe.Recognized)
{
recognized = true;
Console.Write(stExe.Information);
if(((AtariST)stExe).resourceStream != null ||
(((AtariST)stExe).ResourceHeader.rsh_vrsn != 0 && ((AtariST)stExe).ResourceHeader.rsh_vrsn != 1 &&
((AtariST)stExe).ResourceHeader.rsh_vrsn != 4 && ((AtariST)stExe).ResourceHeader.rsh_vrsn != 5))
if(((AtariST)stExe).resourceStream != null || ((AtariST)stExe).ResourceHeader.rsh_vrsn != 0 &&
((AtariST)stExe).ResourceHeader.rsh_vrsn != 1 &&
((AtariST)stExe).ResourceHeader.rsh_vrsn != 4 &&
((AtariST)stExe).ResourceHeader.rsh_vrsn != 5)
{
Console.WriteLine("\tResources:");
Console.WriteLine("\t\t{0} OBJECTs start at {1}", ((AtariST)stExe).ResourceHeader.rsh_nobs, ((AtariST)stExe).ResourceHeader.rsh_object);
Console.WriteLine("\t\t{0} TEDINFOs start at {1}", ((AtariST)stExe).ResourceHeader.rsh_nted, ((AtariST)stExe).ResourceHeader.rsh_tedinfo);
Console.WriteLine("\t\t{0} ICONBLKs start at {1}", ((AtariST)stExe).ResourceHeader.rsh_nib, ((AtariST)stExe).ResourceHeader.rsh_iconblk);
Console.WriteLine("\t\t{0} BITBLKs start at {1}", ((AtariST)stExe).ResourceHeader.rsh_nbb, ((AtariST)stExe).ResourceHeader.rsh_bitblk);
Console.WriteLine("\t\t{0} object trees start at {1}", ((AtariST)stExe).ResourceHeader.rsh_ntree, ((AtariST)stExe).ResourceHeader.rsh_trindex);
Console.WriteLine("\t\t{0} free strings start at {1}", ((AtariST)stExe).ResourceHeader.rsh_nstring, ((AtariST)stExe).ResourceHeader.rsh_frstr);
Console.WriteLine("\t\t{0} free images start at {1}", ((AtariST)stExe).ResourceHeader.rsh_nimages, ((AtariST)stExe).ResourceHeader.rsh_frimg);
Console.WriteLine("\t\t{0} OBJECTs start at {1}", ((AtariST)stExe).ResourceHeader.rsh_nobs,
((AtariST)stExe).ResourceHeader.rsh_object);
Console.WriteLine("\t\t{0} TEDINFOs start at {1}", ((AtariST)stExe).ResourceHeader.rsh_nted,
((AtariST)stExe).ResourceHeader.rsh_tedinfo);
Console.WriteLine("\t\t{0} ICONBLKs start at {1}", ((AtariST)stExe).ResourceHeader.rsh_nib,
((AtariST)stExe).ResourceHeader.rsh_iconblk);
Console.WriteLine("\t\t{0} BITBLKs start at {1}", ((AtariST)stExe).ResourceHeader.rsh_nbb,
((AtariST)stExe).ResourceHeader.rsh_bitblk);
Console.WriteLine("\t\t{0} object trees start at {1}", ((AtariST)stExe).ResourceHeader.rsh_ntree,
((AtariST)stExe).ResourceHeader.rsh_trindex);
Console.WriteLine("\t\t{0} free strings start at {1}", ((AtariST)stExe).ResourceHeader.rsh_nstring,
((AtariST)stExe).ResourceHeader.rsh_frstr);
Console.WriteLine("\t\t{0} free images start at {1}", ((AtariST)stExe).ResourceHeader.rsh_nimages,
((AtariST)stExe).ResourceHeader.rsh_frimg);
Console.WriteLine("\t\tString data starts at {0}", ((AtariST)stExe).ResourceHeader.rsh_string);
Console.WriteLine("\t\tImage data starts at {0}", ((AtariST)stExe).ResourceHeader.rsh_imdata);
Console.WriteLine("\t\tStandard resource data is {0} bytes", ((AtariST)stExe).ResourceHeader.rsh_rssize);
Console.WriteLine("\t\tImage data starts at {0}", ((AtariST)stExe).ResourceHeader.rsh_imdata);
Console.WriteLine("\t\tStandard resource data is {0} bytes",
((AtariST)stExe).ResourceHeader.rsh_rssize);
if(((AtariST)stExe).ResourceObjectRoot != null)
{
Console.WriteLine("\tObject tree:");
PrintAtariResourceTree(((AtariST)stExe).ResourceObjectRoot, 2);
}
if(((AtariST)stExe).ResourceObjectRoots != null && ((AtariST)stExe).ResourceObjectRoots.Length > 0)
for(int i = 0; i < ((AtariST)stExe).ResourceObjectRoots.Length; i++)
{
Console.WriteLine("\tObject tree {0}:", i);
PrintAtariResourceTree(((AtariST)stExe).ResourceObjectRoots[i], 2);
}
}
if(stExe.Strings != null && stExe.Strings.Any())
{
Console.WriteLine("\tStrings:");
foreach(string str in stExe.Strings) Console.WriteLine("\t\t{0}", str);
}
}
@@ -170,6 +210,12 @@ namespace exeinfo
{
recognized = true;
Console.Write(coffExe.Information);
if(coffExe.Strings != null && coffExe.Strings.Any())
{
Console.WriteLine("\tStrings:");
foreach(string str in coffExe.Strings) Console.WriteLine("\t\t{0}", str);
}
}
if(!recognized) Console.WriteLine("Executable format not recognized");
@@ -177,11 +223,106 @@ namespace exeinfo
static void PrintAtariResourceTree(AtariST.TreeObjectNode node, int level)
{
for(int i = 0; i < level; i++)
Console.Write("\t");
for(int i = 0; i < level; i++) Console.Write("\t");
Console.WriteLine("{0} ({1} {2}) data = {3}, coordinates ({4},{5}) size {6}x{7}", node.type, node.flags,
node.state, node.data, node.x, node.y, node.width, node.height);
string thickStr;
switch(node.type)
{
case AtariST.ObjectTypes.G_BOX:
case AtariST.ObjectTypes.G_IBOX:
Console.WriteLine("{0} ({1} {2}) {3} border, {4} text, {5} interior, {6} fill, {7} mode, coordinates ({8},{9}) size {10}x{11}",
node.type, node.flags, node.state,
(AtariST.ObjectColors)((node.data & 0xFFFF & AtariST.BorderColorMask) >> 12),
(AtariST.ObjectColors)((node.data & 0xFFFF & AtariST.TextColorMask) >> 8),
(AtariST.ObjectColors)((node.data & 0xFFFF & AtariST.InsideColorMask) >> 8),
(AtariST.ObjectFillPattern)((node.data & 0xFFFF & AtariST.FillPatternMask) >> 4),
(node.data & 0xFFFF & AtariST.TransparentColor) != 0
? "transparent"
: "replace",
node.x, node.y, node.width, node.height);
break;
case AtariST.ObjectTypes.G_BOXCHAR:
sbyte thickness = (sbyte)((node.data & 0xFF0000) >> 16);
if(thickness < 0) thickStr = $"{thickness * -1} pixels outward thickness";
else if(thickness > 0)
thickStr = $"{thickness} pixels inward thickness";
else
thickStr = "no thickness";
char character =
Claunia.Encoding.Encoding.AtariSTEncoding.GetString(new[]
{
(byte)((node.data & 0xFF000000) >> 24)
})[0];
Console.WriteLine(
"{0} ({1} {2}) {3} border, {4} text, {5} interior, {6} fill, {7} mode, {8}, '{9}' character, coordinates ({10},{11}) size {12}x{13}",
node.type, node.flags, node.state,
(AtariST.ObjectColors)((node.data & 0xFFFF & AtariST.BorderColorMask) >> 12),
(AtariST.ObjectColors)((node.data & 0xFFFF & AtariST.TextColorMask) >> 8),
(AtariST.ObjectColors)((node.data & 0xFFFF & AtariST.InsideColorMask) >> 8),
(AtariST.ObjectFillPattern)((node.data & 0xFFFF & AtariST.FillPatternMask) >> 4),
(node.data & 0xFFFF & AtariST.TransparentColor) != 0
? "transparent"
: "replace",
thickStr, character, node.x, node.y, node.width, node.height);
break;
case AtariST.ObjectTypes.G_BUTTON:
case AtariST.ObjectTypes.G_STRING:
case AtariST.ObjectTypes.G_TITLE:
Console.WriteLine("{0} ({1} {2}), coordinates ({3},{4}) size {5}x{6}: {7}", node.type, node.flags,
node.state, node.x, node.y, node.width, node.height, node.String);
break;
case AtariST.ObjectTypes.G_TEXT:
case AtariST.ObjectTypes.G_BOXTEXT:
case AtariST.ObjectTypes.G_FTEXT:
case AtariST.ObjectTypes.G_FBOXTEXT:
if(node.TedInfo == null) goto default;
if(node.TedInfo.Thickness < 0)
thickStr = $"{node.TedInfo.Thickness * -1} pixels outward thickness";
else if(node.TedInfo.Thickness > 0)
thickStr = $"{node.TedInfo.Thickness} pixels inward thickness";
else
thickStr = "no thickness";
Console.WriteLine("{0} ({1} {2}), coordinates ({3},{4}) size {5}x{6}, font {7}, {8}-justified, {9}," + " {10} border, {11} text, {12} interior, {13} fill, {14} mode, text: \"{15}\"," + " validation: \"{16}\", template: \"{17}\"",
node.type, node.flags, node.state, node.x, node.y, node.width, node.height,
node.TedInfo.Font, node.TedInfo.Justification, thickStr, node.TedInfo.BorderColor,
node.TedInfo.TextColor, node.TedInfo.InsideColor, node.TedInfo.Fill,
node.TedInfo.Transparency ? "transparent" : "replace", node.TedInfo.Text,
node.TedInfo.Validation, node.TedInfo.Template);
break;
case AtariST.ObjectTypes.G_IMAGE:
if(node.BitBlock == null) goto default;
Console.WriteLine("{0} ({1} {2}), coordinates ({3},{4}) size {5}x{6}, colored {7}, {8} bytes", node.type,
node.flags, node.state, node.BitBlock.X, node.BitBlock.Y, node.BitBlock.Width,
node.BitBlock.Height, node.BitBlock.Color, node.BitBlock.Data?.Length);
break;
/*
case AtariST.ObjectTypes.G_USERDEF: break;*/
case AtariST.ObjectTypes.G_ICON:
if(node.IconBlock == null) goto default;
Console.WriteLine(
"{0} ({1} {2}), coordinates ({3},{4}) size {5}x{6}, {7} foreground," +
" {8} background, char '{9}' at ({10},{11}), {12} bytes data, text \"{13}\" at" +
" ({14},{15}) within a box {16}x{17} pixels", node.type, node.flags, node.state,
node.IconBlock.X, node.IconBlock.Y, node.IconBlock.Width, node.IconBlock.Height,
node.IconBlock.ForegroundColor, node.IconBlock.BackgroundColor,
node.IconBlock.Character, node.IconBlock.CharX, node.IconBlock.CharY,
node.IconBlock.Data?.Length, node.IconBlock.Text, node.IconBlock.TextX,
node.IconBlock.TextY, node.IconBlock.TextWidth, node.IconBlock.TextHeight);
break;
default:
Console.WriteLine("{0} ({1} {2}) data = {3}, coordinates ({4},{5}) size {6}x{7}", node.type,
node.flags, node.state, node.data, node.x, node.y, node.width, node.height);
break;
}
if(node.child != null) PrintAtariResourceTree(node.child, level + 1);

4
exeinfo/packages.config Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Claunia.Encoding" version="1.4.0" targetFramework="net461" />
</packages>

View File

@@ -27,6 +27,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
namespace libexeinfo
@@ -102,10 +103,10 @@ namespace libexeinfo
public IEnumerable<Architecture> Architectures => new[] {Architecture.M68K};
public OperatingSystem RequiredOperatingSystem =>
new OperatingSystem {Name = Header.mint == MINT_SIGNATURE ? "MiNT" : "Atari TOS"};
public IEnumerable<string> Strings { get; }
public IEnumerable<string> Strings { get; private set; }
public Stream resourceStream;
public AtariResourceHeader ResourceHeader;
public TreeObjectNode ResourceObjectRoot;
public TreeObjectNode[] ResourceObjectRoots;
void Initialize()
{
@@ -132,20 +133,63 @@ namespace libexeinfo
if(ResourceHeader.rsh_vrsn != 0 && ResourceHeader.rsh_vrsn != 1 && ResourceHeader.rsh_vrsn != 4 && ResourceHeader.rsh_vrsn != 5) return;
if(ResourceHeader.rsh_nobs > 0)
List<string> strings = new List<string>();
if(ResourceHeader.rsh_ntree > 0)
{
resourceStream.Position = ResourceHeader.rsh_trindex;
int[] treeOffsets = new int[ResourceHeader.rsh_ntree];
byte[] tmp = new byte[4];
for(int i = 0; i < ResourceHeader.rsh_ntree; i++)
{
resourceStream.Read(tmp, 0, 4);
treeOffsets[i] = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
}
ResourceObjectRoots = new TreeObjectNode[ResourceHeader.rsh_ntree];
for(int i = 0; i < ResourceHeader.rsh_ntree; i++)
{
if(treeOffsets[i] <= 0 || treeOffsets[i] >= resourceStream.Length) continue;
resourceStream.Position = treeOffsets[i];
List<ObjectNode> nodes = new List<ObjectNode>();
while(true)
{
buffer = new byte[Marshal.SizeOf(typeof(ObjectNode))];
resourceStream.Read(buffer, 0, buffer.Length);
ObjectNode node = BigEndianMarshal.ByteArrayToStructureBigEndian<ObjectNode>(buffer);
nodes.Add(node);
if(((ObjectFlags)node.ob_flags).HasFlag(ObjectFlags.Lastob)) break;
}
List<short> knownNodes = new List<short>();
ResourceObjectRoots[i] = ProcessResourceObject(nodes, ref knownNodes, 0, resourceStream, strings);
}
}
else if(ResourceHeader.rsh_nobs > 0)
{
ObjectNode[] nodes = new ObjectNode[ResourceHeader.rsh_nobs];
resourceStream.Position = ResourceHeader.rsh_object;
for(short i = 0; i < ResourceHeader.rsh_nobs; i++)
{
buffer = new byte[Marshal.SizeOf(typeof(ObjectNode))];
buffer = new byte[Marshal.SizeOf(typeof(ObjectNode))];
resourceStream.Read(buffer, 0, buffer.Length);
nodes[i] = BigEndianMarshal.ByteArrayToStructureBigEndian<ObjectNode>(buffer);
}
List<short> knownNodes = new List<short>();
ResourceObjectRoot = ProcessResourceObject(nodes, ref knownNodes, 0);
ResourceObjectRoots = new TreeObjectNode[1];
ResourceObjectRoots[0] = ProcessResourceObject(nodes, ref knownNodes, 0, resourceStream, strings);
}
if(strings.Count > 0)
{
strings.Sort();
Strings = strings.Distinct();
}
}

View File

@@ -102,7 +102,7 @@ namespace libexeinfo
/// An object that describes a color icon. Its <see cref="ObjectNode.ob_spec" /> is a pointer to an <see cref="ColorIconBlock" />
/// structure.
/// </summary>
G_CICON = 31,
G_CICON = 33,
}
[Flags]
@@ -177,55 +177,68 @@ namespace libexeinfo
public enum ObjectColors : byte
{
White = 0,
Black = 1,
Red = 2,
Green = 3,
Blue = 4,
Cyan = 5,
Yellow = 6,
Magenta = 7,
White2 = 8,
Black2 = 9,
LightRed = 10,
LightGreen = 11,
LightBlue = 12,
LightCyan = 13,
LightYellow = 14,
White = 0,
Black = 1,
Red = 2,
Green = 3,
Blue = 4,
Cyan = 5,
Yellow = 6,
Magenta = 7,
White2 = 8,
Black2 = 9,
LightRed = 10,
LightGreen = 11,
LightBlue = 12,
LightCyan = 13,
LightYellow = 14,
LightMagenta = 15
}
public enum ObjectFillPattern : byte
{
Hollow = 0,
Hollow = 0,
Dither1 = 1,
Dither2 = 2,
Dither3 = 3,
Dither4 = 4,
Dither5 = 5,
Dither6 = 6,
Solid = 7,
Solid = 7,
}
public enum ObjectJustification : short
{
Left = 0,
Right = 1,
Center = 2
}
public enum ObjectFont : short
{
System = 3,
Small = 5
}
/// <summary>
/// Mask for border <see cref="ObjectColors"/>
/// </summary>
const ushort BorderColorMask = 0xF000;
public const ushort BorderColorMask = 0xF000;
/// <summary>
/// Mask for text <see cref="ObjectColors"/>
/// </summary>
const ushort TextColorMask = 0x0F00;
public const ushort TextColorMask = 0x0F00;
/// <summary>
/// If set text is in transparent mode. Replace mode otherwise.
/// </summary>
const ushort TransparentColor = 0x0080;
public const ushort TransparentColor = 0x0080;
/// <summary>
/// Mask for <see cref="ObjectFillPattern"/>
/// </summary>
const ushort FillPatternMask = 0x0070;
public const ushort FillPatternMask = 0x0070;
/// <summary>
/// Mask for inside <see cref="ObjectColors"/>
/// </summary>
const ushort InsideColorMask = 0x000F;
public const ushort InsideColorMask = 0x000F;
}
}

View File

@@ -24,16 +24,18 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using Claunia.Encoding;
namespace libexeinfo
{
public partial class AtariST : IExecutable
{
static TreeObjectNode ProcessResourceObject(IList<ObjectNode> nodes, ref List<short> knownNodes, short nodeNumber)
static TreeObjectNode ProcessResourceObject(IList<ObjectNode> nodes, ref List<short> knownNodes,
short nodeNumber, Stream resourceStream,
List<string> strings)
{
TreeObjectNode node = new TreeObjectNode
{
@@ -47,13 +49,187 @@ namespace libexeinfo
height = nodes[nodeNumber].ob_height
};
byte[] buffer;
List<byte> chars;
switch(node.type)
{
case ObjectTypes.G_TEXT:
case ObjectTypes.G_BOXTEXT:
case ObjectTypes.G_FTEXT:
case ObjectTypes.G_FBOXTEXT:
if(node.data <= 0 || node.data >= resourceStream.Length) break;
resourceStream.Position = node.data;
buffer = new byte[Marshal.SizeOf(typeof(TedInfo))];
resourceStream.Read(buffer, 0, buffer.Length);
TedInfo ted = BigEndianMarshal.ByteArrayToStructureBigEndian<TedInfo>(buffer);
node.TedInfo = new TextBlock
{
Font = (ObjectFont)ted.te_font,
Justification = (ObjectJustification)ted.te_just,
BorderColor = (ObjectColors)((ted.te_color & BorderColorMask) >> 12),
TextColor = (ObjectColors)((ted.te_color & TextColorMask) >> 8),
Transparency = (ted.te_color & TransparentColor) != TransparentColor,
Fill = (ObjectFillPattern)((ted.te_color & FillPatternMask) >> 4),
InsideColor = (ObjectColors)(ted.te_color & InsideColorMask),
Thickness = ted.te_thickness
};
byte[] tmpStr;
if(ted.te_ptext > 0 && ted.te_ptext < resourceStream.Length && ted.te_txtlen > 1)
{
tmpStr = new byte[ted.te_txtlen - 1];
resourceStream.Position = ted.te_ptext;
resourceStream.Read(tmpStr, 0, ted.te_txtlen - 1);
node.TedInfo.Text = Encoding.AtariSTEncoding.GetString(tmpStr);
strings.Add(node.TedInfo.Text.Trim());
}
if(ted.te_pvalid > 0 && ted.te_pvalid < resourceStream.Length && ted.te_txtlen > 1)
{
tmpStr = new byte[ted.te_txtlen - 1];
resourceStream.Position = ted.te_pvalid;
resourceStream.Read(tmpStr, 0, ted.te_txtlen - 1);
node.TedInfo.Validation = Encoding.AtariSTEncoding.GetString(tmpStr);
strings.Add(node.TedInfo.Validation.Trim());
}
if(ted.te_ptmplt > 0 && ted.te_ptmplt < resourceStream.Length && ted.te_tmplen > 1)
{
tmpStr = new byte[ted.te_tmplen - 1];
resourceStream.Position = ted.te_ptmplt;
resourceStream.Read(tmpStr, 0, ted.te_tmplen - 1);
node.TedInfo.Template = Encoding.AtariSTEncoding.GetString(tmpStr);
strings.Add(node.TedInfo.Template.Trim());
}
break;
// TODO: This is indeed a CUT from a bigger image, need to cut it out
case ObjectTypes.G_IMAGE:
if(node.data <= 0 || node.data >= resourceStream.Length) break;
resourceStream.Position = node.data;
buffer = new byte[Marshal.SizeOf(typeof(BitBlock))];
resourceStream.Read(buffer, 0, buffer.Length);
BitBlock bitBlock = BigEndianMarshal.ByteArrayToStructureBigEndian<BitBlock>(buffer);
node.BitBlock = new BitmapBlock
{
Color = (ObjectColors)bitBlock.bi_color,
Height = bitBlock.bi_hl,
Width = bitBlock.bi_wb * 8,
X = bitBlock.bi_x,
Y = bitBlock.bi_y
};
if(bitBlock.bi_pdata == 0 || bitBlock.bi_pdata >= resourceStream.Length) break;
node.BitBlock.Data = new byte[bitBlock.bi_wb * bitBlock.bi_hl];
resourceStream.Position = bitBlock.bi_pdata;
resourceStream.Read(node.BitBlock.Data, 0, node.BitBlock.Data.Length);
break;
case ObjectTypes.G_USERDEF:
if(node.data <= 0 || node.data >= resourceStream.Length) break;
resourceStream.Position = node.data;
buffer = new byte[Marshal.SizeOf(typeof(UserBlock))];
resourceStream.Read(buffer, 0, buffer.Length);
node.UserBlock = BigEndianMarshal.ByteArrayToStructureBigEndian<UserBlock>(buffer);
break;
case ObjectTypes.G_ICON:
if(node.data <= 0 || node.data >= resourceStream.Length) break;
resourceStream.Position = node.data;
buffer = new byte[Marshal.SizeOf(typeof(IconBlock))];
resourceStream.Read(buffer, 0, buffer.Length);
IconBlock iconBlock = BigEndianMarshal.ByteArrayToStructureBigEndian<IconBlock>(buffer);
node.IconBlock = new Icon
{
Width = iconBlock.ib_wicon,
Height = iconBlock.ib_hicon,
X = iconBlock.ib_xicon,
Y = iconBlock.ib_yicon,
ForegroundColor = (ObjectColors)((iconBlock.ib_char >> 12) & 0x000F),
BackgroundColor = (ObjectColors)((iconBlock.ib_char >> 8) & 0x000F),
Character =
Encoding.AtariSTEncoding.GetString(new[] {(byte)(iconBlock.ib_char & 0xFF)})[0],
CharX = iconBlock.ib_xchar,
CharY = iconBlock.ib_ychar,
TextX = iconBlock.ib_xtext,
TextY = iconBlock.ib_ytext,
TextWidth = iconBlock.ib_wtext,
TextHeight = iconBlock.ib_htext
};
if(iconBlock.ib_ptext > 0 && iconBlock.ib_ptext < resourceStream.Length)
{
resourceStream.Position = iconBlock.ib_ptext;
chars = new List<byte>();
while(true)
{
int character = resourceStream.ReadByte();
if(character <= 0) break;
chars.Add((byte)character);
}
node.IconBlock.Text = Encoding.AtariSTEncoding.GetString(chars.ToArray());
strings.Add(node.IconBlock.Text.Trim());
}
if(iconBlock.ib_pdata > 0 && iconBlock.ib_pdata < resourceStream.Length)
{
resourceStream.Position = iconBlock.ib_pdata;
node.IconBlock.Data = new byte[node.IconBlock.Width * node.IconBlock.Height / 8];
resourceStream.Read(node.IconBlock.Data, 0, node.IconBlock.Data.Length);
}
if(iconBlock.ib_pmask > 0 && iconBlock.ib_pmask < resourceStream.Length)
{
resourceStream.Position = iconBlock.ib_pmask;
node.IconBlock.Mask = new byte[node.IconBlock.Width * node.IconBlock.Height / 8];
resourceStream.Read(node.IconBlock.Mask, 0, node.IconBlock.Mask.Length);
}
break;
case ObjectTypes.G_CICON:
//Console.WriteLine("ColorIconBlock pointer {0}", node.data);
break;
case ObjectTypes.G_BUTTON:
case ObjectTypes.G_STRING:
case ObjectTypes.G_TITLE:
if(node.data <= 0 || node.data >= resourceStream.Length) break;
resourceStream.Position = node.data;
chars = new List<byte>();
while(true)
{
int character = resourceStream.ReadByte();
if(character <= 0) break;
chars.Add((byte)character);
}
node.String = Encoding.AtariSTEncoding.GetString(chars.ToArray());
strings.Add(node.String.Trim());
break;
}
knownNodes.Add(nodeNumber);
if(nodes[nodeNumber].ob_head > 0 && !knownNodes.Contains(nodes[nodeNumber].ob_head))
node.child = ProcessResourceObject(nodes, ref knownNodes, nodes[nodeNumber].ob_head);
node.child = ProcessResourceObject(nodes, ref knownNodes, nodes[nodeNumber].ob_head, resourceStream,
strings);
if(nodes[nodeNumber].ob_next > 0 && !knownNodes.Contains(nodes[nodeNumber].ob_next))
node.sibling = ProcessResourceObject(nodes, ref knownNodes, nodes[nodeNumber].ob_next);
node.sibling =
ProcessResourceObject(nodes, ref knownNodes, nodes[nodeNumber].ob_next, resourceStream, strings);
return node;
}

View File

@@ -207,6 +207,57 @@ namespace libexeinfo
public short y;
public short width;
public short height;
public TextBlock TedInfo;
public BitmapBlock BitBlock;
public UserBlock UserBlock;
public Icon IconBlock;
public string String;
}
public class TextBlock
{
public string Text;
public string Template;
public string Validation;
public ObjectFont Font;
public ObjectJustification Justification;
public short Thickness;
public ObjectColors BorderColor;
public ObjectColors TextColor;
public ObjectColors InsideColor;
public bool Transparency;
public ObjectFillPattern Fill;
}
public class BitmapBlock
{
public byte[] Data;
public int Width;
public int Height;
public short X;
public short Y;
public ObjectColors Color;
}
public class Icon
{
public byte[] Mask;
public byte[] Data;
public int Width;
public int Height;
public short X;
public short Y;
public ObjectColors BackgroundColor;
public ObjectColors ForegroundColor;
public char Character;
public short CharX;
public short CharY;
public string Text;
public short TextX;
public short TextY;
public short TextWidth;
public short TextHeight;
}
/// <summary>