diff --git a/exeinfo/Program.cs b/exeinfo/Program.cs index 85f4564..c171167 100644 --- a/exeinfo/Program.cs +++ b/exeinfo/Program.cs @@ -201,7 +201,7 @@ namespace exeinfo if(!recognized) Console.WriteLine("Executable format not recognized"); } - static void PrintGemResources(GEM.GemResourceHeader resourceHeader, IReadOnlyList roots, + static void PrintGemResources(GEM.MagiCResourceHeader resourceHeader, IReadOnlyList roots, GEM.GemResourceExtension resourceExtension, GEM.ColorIcon[] colorIcons) { diff --git a/libexeinfo/AtariST/AtariST.cs b/libexeinfo/AtariST/AtariST.cs index 2aeaa2d..0a821bc 100644 --- a/libexeinfo/AtariST/AtariST.cs +++ b/libexeinfo/AtariST/AtariST.cs @@ -40,7 +40,7 @@ namespace libexeinfo { public GEM.ColorIcon[] GemColorIcons; public GEM.GemResourceExtension ResourceExtension; - public GEM.GemResourceHeader ResourceHeader; + public GEM.MagiCResourceHeader ResourceHeader; public GEM.TreeObjectNode[] ResourceObjectRoots; public Stream ResourceStream; @@ -133,10 +133,20 @@ namespace libexeinfo buffer = new byte[Marshal.SizeOf(typeof(GEM.GemResourceHeader))]; ResourceStream.Position = 0; ResourceStream.Read(buffer, 0, buffer.Length); - ResourceHeader = BigEndianMarshal.ByteArrayToStructureBigEndian(buffer); + GEM.GemResourceHeader gemResourceHeader = + BigEndianMarshal.ByteArrayToStructureBigEndian(buffer); - if(ResourceHeader.rsh_vrsn != 0 && ResourceHeader.rsh_vrsn != 1 && ResourceHeader.rsh_vrsn != 4 && - ResourceHeader.rsh_vrsn != 5) return; + if(gemResourceHeader.rsh_vrsn != 0 && gemResourceHeader.rsh_vrsn != 1 && gemResourceHeader.rsh_vrsn != 3 && + gemResourceHeader.rsh_vrsn != 4 && gemResourceHeader.rsh_vrsn != 5) return; + + if(gemResourceHeader.rsh_vrsn == 3) + { + buffer = new byte[Marshal.SizeOf(typeof(GEM.MagiCResourceHeader))]; + ResourceStream.Position = 0; + ResourceStream.Read(buffer, 0, buffer.Length); + ResourceHeader = BigEndianMarshal.ByteArrayToStructureBigEndian(buffer); + } + else ResourceHeader = GEM.GemToMagiC(gemResourceHeader); if((ResourceHeader.rsh_vrsn & 4) == 4) { diff --git a/libexeinfo/GEM/Enums.cs b/libexeinfo/GEM/Enums.cs index 4c2fb92..1fb95e1 100644 --- a/libexeinfo/GEM/Enums.cs +++ b/libexeinfo/GEM/Enums.cs @@ -83,7 +83,7 @@ namespace libexeinfo } [Flags] - public enum ObjectFlags : short + public enum ObjectFlags : ushort { /// /// Indicates that the user can select the object @@ -123,7 +123,53 @@ namespace libexeinfo /// /// Indicates that the value in is a pointer to the actual value. /// - Indirect = 0x0100 + Indirect = 0x0100, + /// + /// Under MultiTOS this object creates a three-dimensional object. + /// + Fl3Dind = 0x0200, + /// + /// Pressing the [Esc] key corresponds to the selection of the object with this flag. + /// + EscCancel = 0x0200, + /// + /// In 3D operation this object will be treated as an AES background object. + /// + Fl3DBak = 0x0400, + /// + /// A button with this flag uses a bitmap instead of text. + /// + BitButton = 0x0400, + /// + /// In 3D operation this object will be treated as an activator. + /// + Fl3DAct = 0x0600, + /// + /// In MultiTOS and from MagiC 5.10 this flag indicates submenus. + /// + SubMenu = 0x0800, + /// + /// Pressing the [PAGEUP] key corresponds to the selection of the first object with this flag in the dialog. Pressing + /// the [PAGEDOWN] key corresponds to the selection of the last object with this flag. + /// + Scroller = 0x0800, + /// + /// An object with this flag will be drawn with a 3D border. + /// + Flag3D = 0x1000, + /// + /// The color of the object is not a color index of the VDI, but an entry in a table with colors for designated + /// categories. + /// + UseColorCat = 0x2000, + /// + /// Sunken 3D background + /// + Fl3DBak2 = 0x4000, + /// + /// Not implemented + /// + SubMenu2 = 0x8000 } public enum ObjectFont : short @@ -140,7 +186,7 @@ namespace libexeinfo } [Flags] - public enum ObjectStates : short + public enum ObjectStates : ushort { /// /// Indicates that the object is highlighted by being drawn with reversed colors @@ -165,7 +211,25 @@ namespace libexeinfo /// /// Indicates that the object (usually a box) is drawn with a drop shadow /// - Shadowed = 0x0020 + Shadowed = 0x0020, + /// + /// In PC-GEM ignores icon background. As of MagiC 3 controls the underscoring of character strings. + /// + Whitebak = 0x0040, + /// + /// Indicates that the object is to be drawn with a 3D effect. + /// + Draw3D = 0x0080, + /// + /// An object with this status will be surrounded by a dashed line. + /// + Highlighted = 0x0100, + /// + /// Setting this state undoes the line by + /// + Unhighlighted = 0x0200, + Underline = 0x0F00, + Xstate = 0xF000 } public enum ObjectTypes : short @@ -190,7 +254,8 @@ namespace libexeinfo /// G_IMAGE = 23, /// - /// A programmed defined object. Its is a pointer to a + /// A programmed defined object. Its is a pointer to a + /// /// structure. /// G_USERDEF = 24, @@ -238,10 +303,36 @@ namespace libexeinfo G_TITLE = 32, /// /// An object that describes a color icon. Its is a pointer to an - /// - /// structure. + /// structure. /// - G_CICON = 33 + G_CICON = 33, + /// + /// An object that describes a cycle button (a button which alters its text cyclically when clicked on). + /// Its is a pointer to a structure. + /// + G_SWBUTTON = 34, + /// + /// An object that describes a popup menu. Its is a pointer to a + /// structure. + /// + G_POPUP = 35, + /// + /// This object is user internally by MagiC to depict window titles. + /// + G_WINTITLE = 36, + /// + /// As of MagiC 5.20 an editable object implemented in a shared library. Its is a + /// pointer to the object. + /// + G_EDIT = 37, + /// + /// Similar to , but any keyboard shortcut present is split off and output ranged right. + /// + G_SHORTCUT = 38, + /// + /// Scrolling list + /// + G_SLIST = 39 } /// diff --git a/libexeinfo/GEM/Resources.cs b/libexeinfo/GEM/Resources.cs index ecb4067..3362476 100644 --- a/libexeinfo/GEM/Resources.cs +++ b/libexeinfo/GEM/Resources.cs @@ -157,8 +157,10 @@ namespace libexeinfo buffer = new byte[Marshal.SizeOf(typeof(ApplicationBlock))]; resourceStream.Read(buffer, 0, buffer.Length); node.ApplicationBlock = bigEndian - ? BigEndianMarshal.ByteArrayToStructureBigEndian(buffer) - : BigEndianMarshal.ByteArrayToStructureLittleEndian(buffer); + ? BigEndianMarshal + .ByteArrayToStructureBigEndian(buffer) + : BigEndianMarshal + .ByteArrayToStructureLittleEndian(buffer); break; case ObjectTypes.G_ICON: if(node.data <= 0 || node.data >= resourceStream.Length) break; @@ -178,6 +180,7 @@ namespace libexeinfo case ObjectTypes.G_BUTTON: case ObjectTypes.G_STRING: case ObjectTypes.G_TITLE: + case ObjectTypes.G_SHORTCUT: if(node.data <= 0 || node.data >= resourceStream.Length) break; resourceStream.Position = node.data; @@ -492,5 +495,30 @@ namespace libexeinfo return colorIcons; } + + public static MagiCResourceHeader GemToMagiC(GemResourceHeader header) + { + return new MagiCResourceHeader + { + rsh_vrsn = header.rsh_vrsn, + rsh_object = header.rsh_object, + rsh_tedinfo = header.rsh_tedinfo, + rsh_iconblk = header.rsh_iconblk, + rsh_bitblk = header.rsh_bitblk, + rsh_frstr = header.rsh_frstr, + rsh_string = header.rsh_string, + rsh_imdata = header.rsh_imdata, + rsh_frimg = header.rsh_frimg, + rsh_trindex = header.rsh_trindex, + rsh_nobs = header.rsh_nobs, + rsh_ntree = header.rsh_ntree, + rsh_nted = header.rsh_nted, + rsh_nib = header.rsh_nib, + rsh_nbb = header.rsh_nbb, + rsh_nstring = header.rsh_nstring, + rsh_nimages = header.rsh_nimages, + rsh_rssize = header.rsh_rssize + }; + } } } \ No newline at end of file diff --git a/libexeinfo/GEM/Structs.cs b/libexeinfo/GEM/Structs.cs index fd26215..2331881 100644 --- a/libexeinfo/GEM/Structs.cs +++ b/libexeinfo/GEM/Structs.cs @@ -110,6 +110,88 @@ namespace libexeinfo public short rsh_rssize; } + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct MagiCResourceHeader + { + /// + /// Must be version 3 + /// + public short rsh_vrsn; + /// + /// Not used + /// + public short rsh_extvrsn; + /// + /// Contains an offset from the beginning of the file to the OBJECT structures. + /// + public int rsh_object; + /// + /// Contains an offset from the beginning of the file to the TEDINFO structures. + /// + public int rsh_tedinfo; + /// + /// Contains an offset from the beginning of the file to the ICONBLK structures. + /// + public int rsh_iconblk; + /// + /// Contains an offset from the beginning of the file to the BITBLK structures. + /// + public int rsh_bitblk; + /// + /// Contains an offset from the beginning of the file to the string pointer table. + /// + public int rsh_frstr; + /// + /// Contains an offset from the beginning of the file to the string data. + /// + public int rsh_string; + /// + /// Contains an offset from the beginning of the file to the image data. + /// + public int rsh_imdata; + /// + /// Contains an offset from the beginning of the file to the image pointer table. + /// + public int rsh_frimg; + /// + /// Contains an offset from the beginning of the file to the tree pointer table. + /// + public int rsh_trindex; + /// + /// Number of OBJECTs in the file. + /// + public int rsh_nobs; + /// + /// Number of object trees in the file. + /// + public int rsh_ntree; + /// + /// Number of TEDINFOs in the file. + /// + public int rsh_nted; + /// + /// Number of ICONBLKs in the file. + /// + public int rsh_nib; + /// + /// Number of BITBLKs in the file. + /// + public int rsh_nbb; + /// + /// Number of free strings in the file. + /// + public int rsh_nstring; + /// + /// Number of free images in the file. + /// + public int rsh_nimages; + /// + /// Size of the resource file (in bytes). Note that this is the size of the old format resource file. If the newer + /// format file is being used then this value can be used as an offset to the extension array. + /// + public int rsh_rssize; + } + [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct GemResourceExtension { @@ -191,20 +273,20 @@ namespace libexeinfo [StructLayout(LayoutKind.Sequential, Pack = 1)] public class TreeObjectNode { - public BitmapBlock BitBlock; - public TreeObjectNode child; - public ColorIcon ColorIcon; - public int data; - public ObjectFlags flags; - public short height; - public Icon IconBlock; - public TreeObjectNode sibling; - public ObjectStates state; - public string String; + public ApplicationBlock ApplicationBlock; + public BitmapBlock BitBlock; + public TreeObjectNode child; + public ColorIcon ColorIcon; + public int data; + public ObjectFlags flags; + public short height; + public Icon IconBlock; + public TreeObjectNode sibling; + public ObjectStates state; + public string String; public TextBlock TedInfo; public ObjectTypes type; - public ApplicationBlock ApplicationBlock; public short width; public short x; public short y; @@ -432,7 +514,8 @@ namespace libexeinfo /// /// The APPLBLK structure is used to locate and call an application-defined routine that will draw and/or change an - /// object. The object type G_USERDEF points with its pointer to an USERBLK structure. + /// object. The object type G_USERDEF points with its pointer to an USERBLK + /// structure. /// [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct ApplicationBlock @@ -442,7 +525,7 @@ namespace libexeinfo /// public int ab_code; /// - /// A pointer to a + /// A pointer to a /// public int ab_parm; } @@ -502,12 +585,14 @@ namespace libexeinfo /// public short pb_hc; /// - /// A long value, identical to , that is passed to the application when it is time for + /// A long value, identical to , that is passed to the application when it is + /// time for /// the application to draw or change the object. Low word. /// public short pb_parm_low; /// - /// A long value, identical to , that is passed to the application when it is time for + /// A long value, identical to , that is passed to the application when it is + /// time for /// the application to draw or change the object. High word. /// public short pb_parm_high; @@ -545,5 +630,35 @@ namespace libexeinfo /// public int next_res; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct PopInfoBlock + { + /// + /// Points to the start of an object tree that corresponds to the popup menu + /// + public int tree; + /// + /// Current object of + /// + public short obnum; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct SwInfoBlock + { + /// + /// Points to the string + /// + public int str; + /// + /// Index of the current character string + /// + public short num; + /// + /// Maximum permitted number + /// + public short maxnum; + } } } \ No newline at end of file diff --git a/libexeinfo/MZ/MZ.cs b/libexeinfo/MZ/MZ.cs index 85e2765..dc342d5 100644 --- a/libexeinfo/MZ/MZ.cs +++ b/libexeinfo/MZ/MZ.cs @@ -44,7 +44,7 @@ namespace libexeinfo /// internal MZHeader Header; public GEM.GemResourceExtension ResourceExtension; - public GEM.GemResourceHeader ResourceHeader; + public GEM.MagiCResourceHeader ResourceHeader; public GEM.TreeObjectNode[] ResourceObjectRoots; public Stream ResourceStream; @@ -149,10 +149,20 @@ namespace libexeinfo buffer = new byte[Marshal.SizeOf(typeof(GEM.GemResourceHeader))]; ResourceStream.Position = 0; ResourceStream.Read(buffer, 0, buffer.Length); - ResourceHeader = BigEndianMarshal.ByteArrayToStructureLittleEndian(buffer); + GEM.GemResourceHeader gemResourceHeader = + BigEndianMarshal.ByteArrayToStructureLittleEndian(buffer); - if(ResourceHeader.rsh_vrsn != 0 && ResourceHeader.rsh_vrsn != 1 && ResourceHeader.rsh_vrsn != 4 && - ResourceHeader.rsh_vrsn != 5) return; + if(gemResourceHeader.rsh_vrsn != 0 && gemResourceHeader.rsh_vrsn != 1 && gemResourceHeader.rsh_vrsn != 3 && + gemResourceHeader.rsh_vrsn != 4 && gemResourceHeader.rsh_vrsn != 5) return; + + if(gemResourceHeader.rsh_vrsn == 3) + { + buffer = new byte[Marshal.SizeOf(typeof(GEM.MagiCResourceHeader))]; + ResourceStream.Position = 0; + ResourceStream.Read(buffer, 0, buffer.Length); + ResourceHeader = BigEndianMarshal.ByteArrayToStructureLittleEndian(buffer); + } + else ResourceHeader = GEM.GemToMagiC(gemResourceHeader); if((ResourceHeader.rsh_vrsn & 4) == 4) {