115 lines
4.3 KiB
C
115 lines
4.3 KiB
C
#ifndef NELOAD_H
|
|
#define NELOAD_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include "neformat.h"
|
|
#include "wintypes.h"
|
|
|
|
// ============================================================================
|
|
// Loaded segment descriptor
|
|
// ============================================================================
|
|
|
|
typedef struct {
|
|
uint32_t linearAddr; // Linear (physical) address of segment data
|
|
uint16_t selector; // DPMI selector for this segment
|
|
uint16_t flags; // Original NE segment flags
|
|
uint32_t size; // Actual size in memory (from minAllocSize or fileLength)
|
|
uint32_t fileSize; // Size of data in the file (0 if no file data)
|
|
bool isCode; // true = code segment, false = data segment
|
|
} LoadedSegT;
|
|
|
|
// ============================================================================
|
|
// Resolved export entry
|
|
// ============================================================================
|
|
|
|
typedef struct {
|
|
uint16_t segIndex; // 1-based segment index
|
|
uint16_t offset; // Offset within segment
|
|
uint16_t selector; // DPMI selector (resolved at load time)
|
|
uint8_t flags; // Entry flags
|
|
} ExportEntryT;
|
|
|
|
// ============================================================================
|
|
// Import resolution callback
|
|
//
|
|
// Called by the NE loader when it encounters an imported reference.
|
|
// The callback should return the far pointer (selector:offset) that the
|
|
// import should resolve to. Return FARPTR16_NULL if the import cannot
|
|
// be resolved (the loader will log a warning and patch in a stub).
|
|
// ============================================================================
|
|
|
|
typedef FarPtr16T (*ImportResolverT)(const char *moduleName, uint16_t ordinal, const char *funcName);
|
|
|
|
// ============================================================================
|
|
// Loaded NE module
|
|
// ============================================================================
|
|
|
|
#define NE_MAX_SEGMENTS 64
|
|
#define NE_MAX_EXPORTS 2048
|
|
#define NE_MAX_MODREFS 16
|
|
|
|
typedef struct {
|
|
// Header info
|
|
NeHeaderT neHeader;
|
|
uint32_t neHeaderFileOffset; // File offset of NE header
|
|
uint16_t sectorAlignShift; // Sector alignment
|
|
|
|
// Module name (from resident name table)
|
|
char moduleName[64];
|
|
|
|
// Segments
|
|
uint16_t segmentCount;
|
|
LoadedSegT segments[NE_MAX_SEGMENTS];
|
|
|
|
// Exports (indexed by ordinal)
|
|
uint16_t exportCount;
|
|
ExportEntryT exports[NE_MAX_EXPORTS];
|
|
|
|
// Module references (imported module names)
|
|
uint16_t modRefCount;
|
|
char modRefNames[NE_MAX_MODREFS][32];
|
|
|
|
// Auto data segment selector (DGROUP)
|
|
uint16_t autoDataSel;
|
|
|
|
// DOS memory block (for conventional memory allocations)
|
|
int dosMemSeg; // DOS memory segment (real mode)
|
|
int dosMemSel; // DOS memory selector (PM)
|
|
uint32_t dosMemSize; // Size in bytes
|
|
|
|
// Is the module valid/loaded?
|
|
bool loaded;
|
|
} NeModuleT;
|
|
|
|
// ============================================================================
|
|
// NE loader functions
|
|
// ============================================================================
|
|
|
|
// Load a NE executable from a file.
|
|
// importResolver is called for each imported reference.
|
|
// Returns true on success.
|
|
bool neLoadModule(NeModuleT *mod, const char *filePath, ImportResolverT resolver);
|
|
|
|
// Unload a previously loaded module, freeing all segments and selectors.
|
|
void neUnloadModule(NeModuleT *mod);
|
|
|
|
// Look up an export by ordinal number.
|
|
// Returns true and fills seg/off/sel if found.
|
|
bool neLookupExport(const NeModuleT *mod, uint16_t ordinal, uint16_t *seg, uint16_t *off, uint16_t *sel);
|
|
|
|
// Look up an export by name (searches the resident name table in the loaded file).
|
|
// Returns the ordinal if found, 0 if not found.
|
|
uint16_t neLookupExportByName(const NeModuleT *mod, const char *name, const char *filePath);
|
|
|
|
// Extend a loaded segment by extraSize bytes.
|
|
// The new space is zeroed. *oldSizeOut receives the original size
|
|
// (i.e., the offset of the new area within the segment).
|
|
// Returns true on success. Fails if the result would exceed 64K.
|
|
bool neExtendSegment(NeModuleT *mod, int segIdx, uint32_t extraSize, uint32_t *oldSizeOut);
|
|
|
|
// Debug: dump module information to stderr.
|
|
void neDumpModule(const NeModuleT *mod);
|
|
|
|
#endif // NELOAD_H
|