@@ -24,12 +24,278 @@ public class NewExecutable : WrapperBase<Models.NewExecutable.Executable>
2424 /// <inheritdoc cref="Models.NewExecutable.Executable.NonResidentNameTable"/>
2525 public Models . NewExecutable . NonResidentNameTableEntry [ ] ? NonResidentNameTable => Model . NonResidentNameTable ;
2626
27+ /// <summary>
28+ /// Address of the overlay, if it exists
29+ /// </summary>
30+ /// <see href="https://codeberg.org/CYBERDEV/REWise/src/branch/master/src/exefile.c"/>
31+ public int OverlayAddress
32+ {
33+ get
34+ {
35+ lock ( _sourceDataLock )
36+ {
37+ // Use the cached data if possible
38+ if ( _overlayAddress != null )
39+ return _overlayAddress . Value ;
40+
41+ // Get the end of the file, if possible
42+ int endOfFile = GetEndOfFile ( ) ;
43+ if ( endOfFile == - 1 )
44+ return - 1 ;
45+
46+ // If a required property is missing
47+ if ( Header == null || SegmentTable == null || ResourceTable ? . ResourceTypes == null )
48+ return - 1 ;
49+
50+ // Search through the segments table to find the furthest
51+ int endOfSectionData = - 1 ;
52+ foreach ( var entry in SegmentTable )
53+ {
54+ int offset = ( entry . Offset << Header . SegmentAlignmentShiftCount ) + entry . Length ;
55+ if ( offset > endOfSectionData )
56+ endOfSectionData = offset ;
57+ }
58+
59+ // Search through the resources table to find the furthest
60+ foreach ( var entry in ResourceTable . ResourceTypes )
61+ {
62+ // Skip invalid entries
63+ if ( entry . ResourceCount == 0 || entry . Resources == null || entry . Resources . Length == 0 )
64+ continue ;
65+
66+ foreach ( var resource in entry . Resources )
67+ {
68+ int offset = ( resource . Offset << ResourceTable . AlignmentShiftCount ) + resource . Length ;
69+ if ( offset > endOfSectionData )
70+ endOfSectionData = offset ;
71+ }
72+ }
73+
74+ // If we didn't find the end of section data
75+ if ( endOfSectionData <= 0 )
76+ endOfSectionData = - 1 ;
77+
78+ // Adjust the position of the data by 705 bytes
79+ // TODO: Investigate what the byte data is
80+ endOfSectionData += 705 ;
81+
82+ // Cache and return the position
83+ _overlayAddress = endOfSectionData ;
84+ return _overlayAddress . Value ;
85+ }
86+ }
87+ }
88+
89+ /// <summary>
90+ /// Overlay data, if it exists
91+ /// </summary>
92+ /// <see href="https://codeberg.org/CYBERDEV/REWise/src/branch/master/src/exefile.c"/>
93+ public byte [ ] ? OverlayData
94+ {
95+ get
96+ {
97+ lock ( _sourceDataLock )
98+ {
99+ // Use the cached data if possible
100+ if ( _overlayData != null )
101+ return _overlayData ;
102+
103+ // Get the end of the file, if possible
104+ int endOfFile = GetEndOfFile ( ) ;
105+ if ( endOfFile == - 1 )
106+ return null ;
107+
108+ // If a required property is missing
109+ if ( Header == null || SegmentTable == null || ResourceTable ? . ResourceTypes == null )
110+ return null ;
111+
112+ // Search through the segments table to find the furthest
113+ int endOfSectionData = - 1 ;
114+ foreach ( var entry in SegmentTable )
115+ {
116+ int offset = ( entry . Offset << Header . SegmentAlignmentShiftCount ) + entry . Length ;
117+ if ( offset > endOfSectionData )
118+ endOfSectionData = offset ;
119+ }
120+
121+ // Search through the resources table to find the furthest
122+ foreach ( var entry in ResourceTable . ResourceTypes )
123+ {
124+ // Skip invalid entries
125+ if ( entry . ResourceCount == 0 || entry . Resources == null || entry . Resources . Length == 0 )
126+ continue ;
127+
128+ foreach ( var resource in entry . Resources )
129+ {
130+ int offset = ( resource . Offset << ResourceTable . AlignmentShiftCount ) + resource . Length ;
131+ if ( offset > endOfSectionData )
132+ endOfSectionData = offset ;
133+ }
134+ }
135+
136+ // If we didn't find the end of section data
137+ if ( endOfSectionData <= 0 )
138+ return null ;
139+
140+ // Adjust the position of the data by 705 bytes
141+ // TODO: Investigate what the byte data is
142+ endOfSectionData += 705 ;
143+
144+ // If we're at the end of the file, cache an empty byte array
145+ if ( endOfSectionData >= endOfFile )
146+ {
147+ _overlayData = [ ] ;
148+ return _overlayData ;
149+ }
150+
151+ // Otherwise, cache and return the data
152+ int overlayLength = endOfFile - endOfSectionData ;
153+ _overlayData = ReadFromDataSource ( endOfSectionData , overlayLength ) ;
154+ return _overlayData ;
155+ }
156+ }
157+ }
158+
159+ /// <summary>
160+ /// Overlay strings, if they exist
161+ /// </summary>
162+ public List < string > ? OverlayStrings
163+ {
164+ get
165+ {
166+ lock ( _sourceDataLock )
167+ {
168+ // Use the cached data if possible
169+ if ( _overlayStrings != null )
170+ return _overlayStrings ;
171+
172+ // Get the end of the file, if possible
173+ int endOfFile = GetEndOfFile ( ) ;
174+ if ( endOfFile == - 1 )
175+ return null ;
176+
177+ // If a required property is missing
178+ if ( Header == null || SegmentTable == null || ResourceTable ? . ResourceTypes == null )
179+ return null ;
180+
181+ // Search through the segments table to find the furthest
182+ int endOfSectionData = - 1 ;
183+ foreach ( var entry in SegmentTable )
184+ {
185+ int offset = ( entry . Offset << Header . SegmentAlignmentShiftCount ) + entry . Length ;
186+ if ( offset > endOfSectionData )
187+ endOfSectionData = offset ;
188+ }
189+
190+ // Search through the resources table to find the furthest
191+ foreach ( var entry in ResourceTable . ResourceTypes )
192+ {
193+ // Skip invalid entries
194+ if ( entry . ResourceCount == 0 || entry . Resources == null || entry . Resources . Length == 0 )
195+ continue ;
196+
197+ foreach ( var resource in entry . Resources )
198+ {
199+ int offset = ( resource . Offset << ResourceTable . AlignmentShiftCount ) + resource . Length ;
200+ if ( offset > endOfSectionData )
201+ endOfSectionData = offset ;
202+ }
203+ }
204+
205+ // If we didn't find the end of section data
206+ if ( endOfSectionData <= 0 )
207+ return null ;
208+
209+ // Adjust the position of the data by 705 bytes
210+ // TODO: Investigate what the byte data is
211+ endOfSectionData += 705 ;
212+
213+ // If we're at the end of the file, cache an empty list
214+ if ( endOfSectionData >= endOfFile )
215+ {
216+ _overlayStrings = [ ] ;
217+ return _overlayStrings ;
218+ }
219+
220+ // TODO: Revisit the 16 MiB limit
221+ // Cap the check for overlay strings to 16 MiB (arbitrary)
222+ int overlayLength = Math . Min ( endOfFile - endOfSectionData , 16 * 1024 * 1024 ) ;
223+
224+ // Otherwise, cache and return the strings
225+ _overlayStrings = ReadStringsFromDataSource ( endOfSectionData , overlayLength , charLimit : 3 ) ;
226+ return _overlayStrings ;
227+ }
228+ }
229+ }
230+
27231 /// <inheritdoc cref="Models.NewExecutable.Executable.ResidentNameTable"/>
28232 public Models . NewExecutable . ResidentNameTableEntry [ ] ? ResidentNameTable => Model . ResidentNameTable ;
29233
234+ /// <inheritdoc cref="Models.NewExecutable.Executable.ResourceTable"/>
235+ public Models . NewExecutable . ResourceTable ? ResourceTable => Model . ResourceTable ;
236+
237+ /// <inheritdoc cref="Models.NewExecutable.Executable.SegmentTable"/>
238+ public Models . NewExecutable . SegmentTableEntry [ ] ? SegmentTable => Model . SegmentTable ;
239+
30240 /// <inheritdoc cref="Models.NewExecutable.Executable.Stub"/>
31241 public Models . MSDOS . Executable ? Stub => Model . Stub ;
32242
243+ /// <summary>
244+ /// Stub executable data, if it exists
245+ /// </summary>
246+ public byte [ ] ? StubExecutableData
247+ {
248+ get
249+ {
250+ lock ( _sourceDataLock )
251+ {
252+ // If we already have cached data, just use that immediately
253+ if ( _stubExecutableData != null )
254+ return _stubExecutableData ;
255+
256+ if ( Stub ? . Header ? . NewExeHeaderAddr == null )
257+ return null ;
258+
259+ // Populate the raw stub executable data based on the source
260+ int endOfStubHeader = 0x40 ;
261+ int lengthOfStubExecutableData = ( int ) Stub . Header . NewExeHeaderAddr - endOfStubHeader ;
262+ _stubExecutableData = ReadFromDataSource ( endOfStubHeader , lengthOfStubExecutableData ) ;
263+
264+ // Cache and return the stub executable data, even if null
265+ return _stubExecutableData ;
266+ }
267+ }
268+ }
269+
270+ #endregion
271+
272+ #region Instance Variables
273+
274+ /// <summary>
275+ /// Address of the overlay, if it exists
276+ /// </summary>
277+ private int ? _overlayAddress = null ;
278+
279+ /// <summary>
280+ /// Overlay data, if it exists
281+ /// </summary>
282+ private byte [ ] ? _overlayData = null ;
283+
284+ /// <summary>
285+ /// Overlay strings, if they exist
286+ /// </summary>
287+ private List < string > ? _overlayStrings = null ;
288+
289+ /// <summary>
290+ /// Stub executable data, if it exists
291+ /// </summary>
292+ private byte [ ] ? _stubExecutableData = null ;
293+
294+ /// <summary>
295+ /// Lock object for reading from the source
296+ /// </summary>
297+ private readonly object _sourceDataLock = new ( ) ;
298+
33299 #endregion
34300
35301 #region Constructors
0 commit comments