mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-28 07:47:02 -05:00
265 lines
5.8 KiB
Rust
265 lines
5.8 KiB
Rust
#pragma description NE header and Standard NE fields
|
|
|
|
import std.mem;
|
|
|
|
struct DOSHeader {
|
|
char signature[2];
|
|
u16 lastPageSize;
|
|
u16 numberOfPages;
|
|
u16 relocations;
|
|
u16 headerSizeInParagraphs;
|
|
u16 minimumAllocatedParagraphs;
|
|
u16 maximumAllocatedParagraphs;
|
|
u16 initialSSValue;
|
|
u16 initialRelativeSPValue;
|
|
u16 checksum;
|
|
u16 initialRelativeIPValue;
|
|
u16 initialCSValue;
|
|
u16 relocationsTablePointer;
|
|
u16 overlayNumber;
|
|
u8 overlayInformation[0x20];
|
|
u32 neHeaderPointer;
|
|
};
|
|
|
|
u16 dosMessageOffset;
|
|
u16 pointedCodeOffset;
|
|
|
|
fn finddosmessage() {
|
|
for (u8 i = 0, $+i < std::mem::read_unsigned(0x3C, 4), i = i + 1) {
|
|
if (std::mem::read_unsigned($+i, 1) == 0xBA) { // MOV instruction
|
|
dosMessageOffset = std::mem::read_unsigned($+i+1, 2);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
fn findpointingcode() {
|
|
for (u8 i = 0, $+i < std::mem::read_unsigned(0x3C, 4), i = i + 1) {
|
|
if (std::mem::read_unsigned($+i, 1) == 0xE8) { // CALL instruction
|
|
pointedCodeOffset = std::mem::read_unsigned($+i+1, 2);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
fn isdosdata(char c) {
|
|
return c == 0x0D || c == '$';
|
|
};
|
|
|
|
struct DOSStub {
|
|
if (findpointingcode()) {
|
|
u8 pointingCode[3];
|
|
u8 code[while(std::mem::read_unsigned($, 1) != 0x00)] @ addressof(this) + pointedCodeOffset + 3;
|
|
char message[while(!isdosdata(std::mem::read_unsigned($, 1)))];
|
|
char data[while(std::mem::read_string($-1, 1) != "$")];
|
|
}
|
|
else {
|
|
finddosmessage();
|
|
if (dosMessageOffset > 0) {
|
|
u8 code[while($ != addressof(this) + dosMessageOffset)];
|
|
char message[while(!isdosdata(std::mem::read_unsigned($, 1)))];
|
|
char data[while(std::mem::read_string($-1, 1) != "$")];
|
|
}
|
|
else {
|
|
char code[while(std::mem::read_unsigned($, 1) != 0x00)];
|
|
}
|
|
}
|
|
};
|
|
|
|
struct FileHeader {
|
|
DOSHeader dosHeader;
|
|
DOSStub dosStub @ dosHeader.headerSizeInParagraphs * 16;
|
|
};
|
|
|
|
FileHeader fileHeader @ 0x00;
|
|
|
|
enum DGroupType : u8 {
|
|
NoAutoData,
|
|
SingleData,
|
|
MultipleData,
|
|
Null
|
|
};
|
|
|
|
fn formatDGroupType(u8 value) {
|
|
DGroupType dgroup = value;
|
|
|
|
return dgroup;
|
|
};
|
|
|
|
enum AppType : u8 {
|
|
None,
|
|
Fullscreen,
|
|
WinPMCompatible,
|
|
UsesWinPM
|
|
};
|
|
|
|
fn formatAppType(u8 value) {
|
|
AppType app = value;
|
|
|
|
return app;
|
|
};
|
|
|
|
bitfield ProgramFlags {
|
|
dGroupType : 2 [[format("formatDGroupType")]];
|
|
globalInitialization : 1;
|
|
protectedModeOnly : 1;
|
|
instructions86 : 1;
|
|
instructions286 : 1;
|
|
instructions386 : 1;
|
|
instructionsX87 : 1;
|
|
};
|
|
|
|
bitfield ApplicationFlags {
|
|
applicationType : 2 [[format("formatAppType")]];
|
|
padding : 1;
|
|
os2Application : 1;
|
|
reserved : 1;
|
|
imageError : 1;
|
|
nonConforming : 1;
|
|
dll : 1;
|
|
};
|
|
|
|
enum OSType : u8 {
|
|
Unknown = 0x00,
|
|
OS2 = 0x01,
|
|
Win16 = 0x02,
|
|
DOS4 = 0x03,
|
|
Win32 = 0x04,
|
|
BorlandOSServices = 0x05,
|
|
PharlapDOSExtenderOS2 = 0x81,
|
|
PharlapDOSExtenderWindows = 0x82
|
|
};
|
|
|
|
bitfield OS2EXEFlags {
|
|
longFilename : 1;
|
|
protectedMode : 1;
|
|
proportionalFonts : 1;
|
|
gangloadArea : 1;
|
|
};
|
|
|
|
struct NEHeader {
|
|
char signature[2];
|
|
u8 majorLinkerVersion;
|
|
u8 minorLinkerVersion;
|
|
u16 entryTableOffset;
|
|
u16 entryTableLength;
|
|
u32 fileCRC;
|
|
ProgramFlags programFlags;
|
|
ApplicationFlags appFlags;
|
|
u16 autoDataSegmentIndex;
|
|
u16 initHeapSize;
|
|
u16 initStackSize;
|
|
u32 entryPoint;
|
|
u32 initialStackPointer;
|
|
u16 segmentCount;
|
|
u16 moduleReferenceCount;
|
|
u16 nonResidentNamesTableSize;
|
|
u16 segmentTableOffset;
|
|
u16 resourceTableOffset;
|
|
u16 residentNamesTableOffset;
|
|
u16 moduleReferenceTableOffset;
|
|
u16 importedNamesTableOffset;
|
|
u8 *nonResidentNamesTablePointer[nonResidentNamesTableSize] : u32;
|
|
u16 moveableEntryCount;
|
|
u16 fileAlignmentSizeShiftCount;
|
|
u16 resourceCount;
|
|
OSType targetOS;
|
|
OS2EXEFlags os2ExeFlags;
|
|
u16 thunksReturnOffset;
|
|
u16 segmentReferenceThunksOffset;
|
|
u16 minimumCodeSwapAreaSize;
|
|
u8 expectedMinorWindowsVersion;
|
|
u8 expectedMajorWindowsVersion;
|
|
};
|
|
|
|
NEHeader neHeader @ fileHeader.dosHeader.neHeaderPointer;
|
|
|
|
bitfield SegmentTableFlags {
|
|
dataSegment : 1;
|
|
typeMask : 2;
|
|
padding : 1;
|
|
moveable : 1;
|
|
padding : 1;
|
|
preloaded : 1;
|
|
padding : 1;
|
|
containsRelocationInfo : 1;
|
|
padding : 1;
|
|
discardPriority : 4;
|
|
};
|
|
|
|
struct SegmentTable {
|
|
u16 segmentDataPointer;
|
|
u16 segmentLength;
|
|
SegmentTableFlags segmentTableFlags;
|
|
u16 minimumAllocationSize;
|
|
};
|
|
|
|
SegmentTable segmentTable[neHeader.segmentCount] @ addressof(neHeader) + neHeader.segmentTableOffset;
|
|
|
|
bitfield BlockFlags {
|
|
padding : 4;
|
|
moveable : 1;
|
|
shared : 1;
|
|
preload : 1;
|
|
padding : 9;
|
|
};
|
|
|
|
struct ResourceTypeInformationBlock {
|
|
u8 *resourcePointer : u16;
|
|
u16 resourceLength;
|
|
BlockFlags flags;
|
|
u16 resourceID;
|
|
u32 reserved;
|
|
};
|
|
|
|
struct ResourceRecord {
|
|
u16 typeID;
|
|
u16 numberOfResources;
|
|
u32 reserved;
|
|
ResourceTypeInformationBlock blocks[numberOfResources];
|
|
};
|
|
|
|
struct ResourceTable {
|
|
u16 alignmentShiftCount;
|
|
ResourceRecord records[neHeader.resourceTableEntryCount];
|
|
u8 stringLength;
|
|
char string[stringLength];
|
|
};
|
|
|
|
ResourceTable resourceTable[neHeader.resourceCount] @ addressof(neHeader) + neHeader.resourceTableOffset;
|
|
|
|
struct ResidentName {
|
|
u8 stringLength;
|
|
char string[stringLength];
|
|
u16 ordinalNumber;
|
|
};
|
|
|
|
ResidentName residentNameTable[while($+1 < addressof(neHeader) + neHeader.moduleReferenceTableOffset)] @ addressof(neHeader) + neHeader.residentNamesTableOffset;
|
|
|
|
struct ModuleReference {
|
|
u16 moduleNameOffset;
|
|
};
|
|
|
|
ModuleReference moduleReferenceTable[neHeader.moduleReferenceCount] @ addressof(neHeader) + neHeader.moduleReferenceTableOffset;
|
|
|
|
struct ImportedNameTable {
|
|
u8 stringLength;
|
|
char string[stringLength];
|
|
};
|
|
|
|
ImportedNameTable importedNameTable[while($ < addressof(neHeader) + neHeader.entryTableOffset)] @ addressof(neHeader) + neHeader.importedNamesTableOffset;
|
|
|
|
enum EntryDataType : u8 {
|
|
Unused,
|
|
Fixed = 0x01 ... 0xFE,
|
|
Moveable
|
|
};
|
|
|
|
struct EntryTable {
|
|
u8 entryCount;
|
|
EntryDataType segmentIndicator;
|
|
};
|
|
|
|
EntryTable entryTable[neHeader.entryTableLength/2] @ addressof(neHeader) + neHeader.entryTableOffset;
|