Skip to content

Commit ca7a109

Browse files
committed
Add more NE extensions
1 parent c54f5b3 commit ca7a109

File tree

2 files changed

+295
-26
lines changed

2 files changed

+295
-26
lines changed

SabreTools.Serialization/Wrappers/NewExecutable.cs

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)