diff --git a/exeinfo/Program.cs b/exeinfo/Program.cs
index 71c8651..af84407 100644
--- a/exeinfo/Program.cs
+++ b/exeinfo/Program.cs
@@ -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);
diff --git a/exeinfo/packages.config b/exeinfo/packages.config
new file mode 100644
index 0000000..2e764ff
--- /dev/null
+++ b/exeinfo/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/libexeinfo/AtariST/AtariST.cs b/libexeinfo/AtariST/AtariST.cs
index 2911818..66c8158 100644
--- a/libexeinfo/AtariST/AtariST.cs
+++ b/libexeinfo/AtariST/AtariST.cs
@@ -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 Architectures => new[] {Architecture.M68K};
public OperatingSystem RequiredOperatingSystem =>
new OperatingSystem {Name = Header.mint == MINT_SIGNATURE ? "MiNT" : "Atari TOS"};
- public IEnumerable Strings { get; }
+ public IEnumerable 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 strings = new List();
+
+ 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 nodes = new List();
+ while(true)
+ {
+ buffer = new byte[Marshal.SizeOf(typeof(ObjectNode))];
+ resourceStream.Read(buffer, 0, buffer.Length);
+ ObjectNode node = BigEndianMarshal.ByteArrayToStructureBigEndian(buffer);
+ nodes.Add(node);
+ if(((ObjectFlags)node.ob_flags).HasFlag(ObjectFlags.Lastob)) break;
+ }
+
+ List knownNodes = new List();
+ 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(buffer);
}
List knownNodes = new List();
- 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();
}
}
diff --git a/libexeinfo/AtariST/Enums.cs b/libexeinfo/AtariST/Enums.cs
index d1783d8..8096948 100644
--- a/libexeinfo/AtariST/Enums.cs
+++ b/libexeinfo/AtariST/Enums.cs
@@ -102,7 +102,7 @@ namespace libexeinfo
/// An object that describes a color icon. Its is a pointer to an
/// structure.
///
- 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
+ }
+
///
/// Mask for border
///
- const ushort BorderColorMask = 0xF000;
+ public const ushort BorderColorMask = 0xF000;
///
/// Mask for text
///
- const ushort TextColorMask = 0x0F00;
+ public const ushort TextColorMask = 0x0F00;
///
/// If set text is in transparent mode. Replace mode otherwise.
///
- const ushort TransparentColor = 0x0080;
+ public const ushort TransparentColor = 0x0080;
///
/// Mask for
///
- const ushort FillPatternMask = 0x0070;
+ public const ushort FillPatternMask = 0x0070;
///
/// Mask for inside
///
- const ushort InsideColorMask = 0x000F;
+ public const ushort InsideColorMask = 0x000F;
}
}
\ No newline at end of file
diff --git a/libexeinfo/AtariST/Resources.cs b/libexeinfo/AtariST/Resources.cs
index b502eb8..9bc0a43 100644
--- a/libexeinfo/AtariST/Resources.cs
+++ b/libexeinfo/AtariST/Resources.cs
@@ -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 nodes, ref List knownNodes, short nodeNumber)
+ static TreeObjectNode ProcessResourceObject(IList nodes, ref List knownNodes,
+ short nodeNumber, Stream resourceStream,
+ List strings)
{
TreeObjectNode node = new TreeObjectNode
{
@@ -47,13 +49,187 @@ namespace libexeinfo
height = nodes[nodeNumber].ob_height
};
+ byte[] buffer;
+ List 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(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(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(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(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();
+ 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();
+ 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;
}
diff --git a/libexeinfo/AtariST/Structs.cs b/libexeinfo/AtariST/Structs.cs
index bab9682..803eb49 100644
--- a/libexeinfo/AtariST/Structs.cs
+++ b/libexeinfo/AtariST/Structs.cs
@@ -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;
}
///