diff --git a/libexeinfo/AtariST/AtariST.cs b/libexeinfo/AtariST/AtariST.cs index 0a821bc..2fdafe6 100644 --- a/libexeinfo/AtariST/AtariST.cs +++ b/libexeinfo/AtariST/AtariST.cs @@ -43,6 +43,7 @@ namespace libexeinfo public GEM.MagiCResourceHeader ResourceHeader; public GEM.TreeObjectNode[] ResourceObjectRoots; public Stream ResourceStream; + SymbolEntry[] symbols; /// /// Initializes a new instance of the class. @@ -123,11 +124,27 @@ namespace libexeinfo BaseStream.Read(buffer, 0, buffer.Length); Header = BigEndianMarshal.ByteArrayToStructureBigEndian(buffer); Recognized = Header.signature == SIGNATURE; + List strings = new List(); if(!Recognized) return; Type = "Atari ST executable"; + if(Header.symb_len != 0) + { + BaseStream.Position = 0x1C + Header.text_len + Header.data_len; + buffer = new byte[Marshal.SizeOf(typeof(SymbolEntry))]; + symbols = new SymbolEntry[Header.symb_len / Marshal.SizeOf(typeof(SymbolEntry))]; + for(int i = 0; i < symbols.Length; i++) + { + BaseStream.Read(buffer, 0, buffer.Length); + symbols[i] = new SymbolEntry(); + symbols[i] = BigEndianMarshal.ByteArrayToStructureBigEndian(buffer); + symbols[i].type = (SymbolType)Swapping.Swap((ushort)symbols[i].type); + strings.Add(StringHandlers.CToString(symbols[i].name, Encoding.AtariSTEncoding)); + } + } + if(ResourceStream == null) return; buffer = new byte[Marshal.SizeOf(typeof(GEM.GemResourceHeader))]; @@ -159,8 +176,6 @@ namespace libexeinfo Encoding.AtariSTEncoding); } - List strings = new List(); - if(ResourceHeader.rsh_ntree > 0) { ResourceStream.Position = ResourceHeader.rsh_trindex; diff --git a/libexeinfo/AtariST/Consts.cs b/libexeinfo/AtariST/Consts.cs index a72420c..39a0ae1 100644 --- a/libexeinfo/AtariST/Consts.cs +++ b/libexeinfo/AtariST/Consts.cs @@ -28,7 +28,9 @@ namespace libexeinfo { public partial class AtariST { - const ushort SIGNATURE = 0x601A; - const uint MINT_SIGNATURE = 0x4D694E54; + const ushort SIGNATURE = 0x601A; + const uint MINT_SIGNATURE = 0x4D694E54; + const ushort PF_FLAGS_MASK = 0xFFCF; + const ushort PF_SHARE_MASK = 0x30; } } \ No newline at end of file diff --git a/libexeinfo/AtariST/Enums.cs b/libexeinfo/AtariST/Enums.cs new file mode 100644 index 0000000..b850630 --- /dev/null +++ b/libexeinfo/AtariST/Enums.cs @@ -0,0 +1,85 @@ +// +// Enums.cs +// +// Author: +// Natalia Portillo +// +// Copyright (c) 2017 Copyright © Claunia.com +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; + +namespace libexeinfo +{ + public partial class AtariST + { + [Flags] + public enum PrgFlags : ushort + { + /// + /// If set clear only the BSS area on program load, otherwise clear the entire heap. + /// + PF_FASTLOAD = 0x01, + /// + /// If set, the program may be loaded into alternative RAM, otherwise it muse be loaded into standard RAM. + /// + PF_TTRAMLOAD = 0x02, + /// + /// If set, the program's malloc() requests may be satisfied from alternative RAM, otherwise they must be satisfied + /// from standard RAM. + /// + PF_TTRAMMEM = 0x04 + } + + public enum PrgSharing : ushort + { + /// + /// The processes' entire memory space will be considered private. + /// + PF_PRIVATE = 0, + /// + /// The processes' entire memory space will be readable and writable by any process. + /// + PF_GLOBAL = 1, + /// + /// The processes' entire memory space will only be readable and writable by itself and any other process in supervisor + /// mode. + /// + PF_SUPERVISOR = 2, + /// + /// The processes' entire memory space will be readable by any application but only writable by itself. + /// + PF_READABLE = 3 + } + + [Flags] + public enum SymbolType : ushort + { + Bss = 0x0100, + Text = 0x0200, + Data = 0x0400, + External = 0x0800, + EquatedRegister = 0x1000, + Global = 0x2000, + Equated = 0x4000, + Defined = 0x8000 + } + } +} \ No newline at end of file diff --git a/libexeinfo/AtariST/Info.cs b/libexeinfo/AtariST/Info.cs index 7889b92..bdc6572 100644 --- a/libexeinfo/AtariST/Info.cs +++ b/libexeinfo/AtariST/Info.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System.Text; +using Encoding = Claunia.Encoding.Encoding; namespace libexeinfo { @@ -34,21 +35,37 @@ namespace libexeinfo /// Gets a string with human readable information for the Atari ST executable represented by this instance /// /// Human readable information for this instance. - public string Information => GetInfo(Header); + public string Information => GetInfo(Header, symbols); /// /// Gets a string with human readable information for a given Atari ST header /// /// Human readable information for given Atari ST header. /// Atari ST executable header. - static string GetInfo(AtariHeader header) + static string GetInfo(AtariHeader header, SymbolEntry[] symbols) { + PrgFlags flags = (PrgFlags)(header.flags & PF_FLAGS_MASK); + PrgSharing sharing = (PrgSharing)((header.flags & PF_SHARE_MASK) >> 4); + StringBuilder sb = new StringBuilder(); sb.AppendLine("Atari ST executable:"); + if(header.mint == MINT_SIGNATURE) sb.AppendLine("\tMiNT executable."); sb.AppendFormat("\t{0} bytes in text segment", header.text_len).AppendLine(); sb.AppendFormat("\t{0} bytes in data segment", header.data_len).AppendLine(); sb.AppendFormat("\t{0} bytes in BSS segment", header.bss_len).AppendLine(); sb.AppendFormat("\t{0} bytes in symbol table", header.symb_len).AppendLine(); + sb.AppendFormat("\tFlags: {0}", flags).AppendLine(); + sb.AppendFormat("\tProcess sharing: {0}", sharing).AppendLine(); + sb.AppendFormat("\t{0} fixups", header.absflags == 0 ? "Has" : "Doesn't have").AppendLine(); + if(symbols == null || symbols.Length <= 0) + return sb.ToString(); + + sb.AppendLine("\tSymbol table:"); + for(int i = 0; i < symbols.Length; i++) + sb.AppendFormat("\t\tSymbol {0}: \"{1}\", type {2}, value {3}", i, + StringHandlers.CToString(symbols[i].name, Encoding.AtariSTEncoding), symbols[i].type, + symbols[i].value).AppendLine(); + return sb.ToString(); } } diff --git a/libexeinfo/AtariST/Structs.cs b/libexeinfo/AtariST/Structs.cs index 168fdae..74e0f57 100644 --- a/libexeinfo/AtariST/Structs.cs +++ b/libexeinfo/AtariST/Structs.cs @@ -42,5 +42,14 @@ namespace libexeinfo public uint flags; public ushort absflags; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct SymbolEntry + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] name; + public SymbolType type; + public uint value; + } } } \ No newline at end of file diff --git a/libexeinfo/libexeinfo.csproj b/libexeinfo/libexeinfo.csproj index 16aad4b..754c682 100644 --- a/libexeinfo/libexeinfo.csproj +++ b/libexeinfo/libexeinfo.csproj @@ -49,6 +49,7 @@ +