diff --git a/if1632/builtin.c b/if1632/builtin.c
index d5c6444a60bb4283f420dbba063d60dce7b09520..8cc9fc8ade616b0cf59809333627f7fd0d892f8d 100644
--- a/if1632/builtin.c
+++ b/if1632/builtin.c
@@ -266,53 +266,33 @@ HMODULE16 BUILTIN_LoadModule( LPCSTR name, BOOL force )
 LPCSTR BUILTIN_GetEntryPoint16( WORD cs, WORD ip, WORD *pOrd )
 {
     static char buffer[80];
-    WORD ordinal, i, max_offset;
+    WORD i, max_offset;
     register BYTE *p;
     NE_MODULE *pModule;
+    ET_BUNDLE *bundle;
+    ET_ENTRY *entry;
 
     if (!(pModule = NE_GetPtr( FarGetOwner16( GlobalHandle16(cs) ))))
         return NULL;
 
-    /* Search for the ordinal */
-
-    p = (BYTE *)pModule + pModule->entry_table;
     max_offset = 0;
-    ordinal = 1;
     *pOrd = 0;
-    while (*p)
-    {
-        switch(p[1])
-        {
-        case 0:    /* unused */
-            ordinal += *p;
-            p += 2;
-            break;
-        case 1:    /* code segment */
-            i = *p;
-            p += 2;
-            while (i-- > 0)
+    bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
+    entry = (ET_ENTRY *)((BYTE *)bundle+6);
+    do {
+	for (i = bundle->first + 1; i < bundle->last; i++)
             {
-                p++;
-                if ((*(WORD *)p <= ip) && (*(WORD *)p >= max_offset))
+	    if ((entry->offs <= ip)
+	    && (entry->type == 1) /* code segment ? */
+	    && (entry->offs >= max_offset))
                 {
-                    max_offset = *(WORD *)p;
-                    *pOrd = ordinal;
-                }
-                p += 2;
-                ordinal++;
-            }
-            break;
-        case 0xff: /* moveable (should not happen in built-in modules) */
-            TRACE( relay, "Built-in module has moveable entry\n" );
-            ordinal += *p;
-            p += 2 + *p * 6;
-            break;
-        default:   /* other segment */
-            ordinal += *p;
-            p += 2 + *p * 3;
-            break;
+		max_offset = entry->offs;
+		*pOrd = i;
         }
+	    entry++;
     }
+    } while ( (bundle->next)
+	   && (bundle = (ET_BUNDLE *)((BYTE *)pModule+bundle->next)));
 
     /* Search for the name in the resident names table */
     /* (built-in modules have no non-resident table)   */
diff --git a/include/module.h b/include/module.h
index 4ae9d7b612cd3a12b9aeca41ced9c9d7cf8e847c..ff320b870a3b6677a15222959d93c6cebc77c662 100644
--- a/include/module.h
+++ b/include/module.h
@@ -56,6 +56,20 @@ typedef struct _NE_MODULE
 } NE_MODULE;
 
 
+typedef struct {
+    BYTE type;
+    BYTE flags;
+    BYTE segnum;
+    WORD offs WINE_PACKED;
+} ET_ENTRY;
+
+typedef struct {
+    WORD first; /* ordinal */
+    WORD last; /* ordinal */
+    WORD next; /* bundle */
+} ET_BUNDLE;
+
+
   /* In-memory segment table */
 typedef struct
 {
diff --git a/loader/ne/module.c b/loader/ne/module.c
index de866c95d59f4b5df148d69e173b49f7bd501570..7856510a67bf8cc398ccc8cff40e4367623cfba2 100644
--- a/loader/ne/module.c
+++ b/loader/ne/module.c
@@ -59,6 +59,8 @@ void NE_DumpModule( HMODULE16 hModule )
     BYTE *pstr;
     WORD *pword;
     NE_MODULE *pModule;
+    ET_BUNDLE *bundle;
+    ET_ENTRY *entry;
 
     if (!(pModule = NE_GetPtr( hModule )))
     {
@@ -143,39 +145,21 @@ void NE_DumpModule( HMODULE16 hModule )
       /* Dump the entry table */
     DUMP( "---\n" );
     DUMP( "Entry table:\n" );
-    pstr = (char *)pModule + pModule->entry_table;
-    ordinal = 1;
-    while (*pstr)
-    {
-        DUMP( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
-        if (!pstr[1])
-        {
-            ordinal += *pstr;
-            pstr += 2;
-        }
-        else if ((BYTE)pstr[1] == 0xff)  /* moveable */
+    bundle = (ET_BUNDLE *)((BYTE *)pModule+pModule->entry_table);    
+    do {
+	entry = (ET_ENTRY *)((BYTE *)bundle+6);
+	DUMP( "Bundle %d-%d: %02x\n", bundle->first, bundle->last, entry->type);
+	ordinal = bundle->first;
+	while (ordinal < bundle->last)
         {
-            i = *pstr;
-            pstr += 2;
-            while (i--)
-            {
-                DUMP( "%d: %02x:%04x (moveable)\n",
-		      ordinal++, pstr[3], *(WORD *)(pstr + 4) );
-                pstr += 6;
-            }
-        }
-        else  /* fixed */
-        {
-            i = *pstr;
-            pstr += 2;
-            while (i--)
-            {
-                DUMP( "%d: %04x (fixed)\n",
-		      ordinal++, *(WORD *)(pstr + 1) );
-                pstr += 3;
-            }
-        }
+	    if (entry->type == 0xff)
+		DUMP("%d: %02x:%04x (moveable)\n", ordinal++, entry->segnum, entry->offs);
+	    else
+		DUMP("%d: %02x:%04x (fixed)\n", ordinal++, entry->segnum, entry->offs);
+	    entry++;
     }
+    } while ( (bundle->next)
+	   && (bundle = ((ET_BUNDLE *)((BYTE *)pModule + bundle->next))) );
 
     /* Dump the non-resident names table */
     DUMP( "---\n" );
@@ -305,43 +289,29 @@ FARPROC16 NE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
 FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop )
 {
     NE_MODULE *pModule;
-    WORD curOrdinal = 1;
-    BYTE *p;
-    WORD sel, offset;
+    WORD sel, offset, i;
+
+    ET_ENTRY *entry;
+    ET_BUNDLE *bundle;
 
     if (!(pModule = NE_GetPtr( hModule ))) return 0;
     assert( !(pModule->flags & NE_FFLAGS_WIN32) );
 
-    p = (BYTE *)pModule + pModule->entry_table;
-    while (*p && (curOrdinal + *p <= ordinal))
+    bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
+    while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
     {
-          /* Skipping this bundle */
-        curOrdinal += *p;
-        switch(p[1])
-        {
-            case 0:    p += 2; break;  /* unused */
-            case 0xff: p += 2 + *p * 6; break;  /* moveable */
-            default:   p += 2 + *p * 3; break;  /* fixed */
-        }
-    }
-    if (!*p) return 0;
-
-    switch(p[1])
-    {
-        case 0:  /* unused */
+	if (!(bundle->next))
             return 0;
-        case 0xff:  /* moveable */
-            p += 2 + 6 * (ordinal - curOrdinal);
-            sel = p[3];
-            offset = *(WORD *)(p + 4);
-            break;
-        default:  /* fixed */
-            sel = p[1];
-            p += 2 + 3 * (ordinal - curOrdinal);
-            offset = *(WORD *)(p + 1);
-            break;
+	bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
     }
 
+    entry = (ET_ENTRY *)((BYTE *)bundle+6);
+    for (i=0; i < (ordinal - bundle->first - 1); i++)
+	entry++;
+
+    sel = entry->segnum;
+    offset = entry->offs;
+
     if (sel == 0xfe) sel = 0xffff;  /* constant entry */
     else sel = GlobalHandleToSel16(NE_SEG_TABLE(pModule)[sel-1].hSeg);
     if (sel==0xffff)
@@ -362,39 +332,26 @@ FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop )
 BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
 {
     NE_MODULE *pModule;
-    WORD curOrdinal = 1;
-    BYTE *p;
+    ET_ENTRY *entry;
+    ET_BUNDLE *bundle;
+    int i;
 
     if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
     assert( !(pModule->flags & NE_FFLAGS_WIN32) );
 
-    p = (BYTE *)pModule + pModule->entry_table;
-    while (*p && (curOrdinal + *p <= ordinal))
-    {
-          /* Skipping this bundle */
-        curOrdinal += *p;
-        switch(p[1])
+    bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
+    while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
         {
-            case 0:    p += 2; break;  /* unused */
-            case 0xff: p += 2 + *p * 6; break;  /* moveable */
-            default:   p += 2 + *p * 3; break;  /* fixed */
-        }
+	bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
+	if (!(bundle->next))
+	    return 0;
     }
-    if (!*p) return FALSE;
 
-    switch(p[1])
-    {
-        case 0:  /* unused */
-            return FALSE;
-        case 0xff:  /* moveable */
-            p += 2 + 6 * (ordinal - curOrdinal);
-            *(WORD *)(p + 4) = offset;
-            break;
-        default:  /* fixed */
-            p += 2 + 3 * (ordinal - curOrdinal);
-            *(WORD *)(p + 1) = offset;
-            break;
-    }
+    entry = (ET_ENTRY *)((BYTE *)bundle+6);
+    for (i=0; i < (ordinal - bundle->first - 1); i++)
+	entry++;
+
+    entry->offs = offset;
     return TRUE;
 }
 
@@ -436,9 +393,11 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
     int size;
     HMODULE16 hModule;
     NE_MODULE *pModule;
-    BYTE *pData;
+    BYTE *pData, *pTempEntryTable;
     char *buffer, *fastload = NULL;
     int fastload_offset = 0, fastload_length = 0;
+    ET_ENTRY *entry;
+    ET_BUNDLE *bundle, *oldbundle;
 
   /* Read a block from either the file or the fast-load area. */
 #define READ(offset,size,buffer) \
@@ -480,6 +439,9 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
            ne_header.entry_tab_offset - ne_header.iname_tab_offset +
              /* entry table length */
            ne_header.entry_tab_length +
+	     /* entry table extra conversion space */
+	   sizeof(ET_BUNDLE) +
+	   2 * (ne_header.entry_tab_length - ne_header.n_mov_entry_points*6) +
              /* loaded file info */
            sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
 
@@ -537,7 +499,8 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
              buffer ))
         {
             HeapFree( SystemHeap, 0, buffer );
-            if (fastload) HeapFree( SystemHeap, 0, fastload );
+            if (fastload)
+		HeapFree( SystemHeap, 0, fastload );
             GlobalFree16( hModule );
             return (HMODULE16)11;  /* invalid exe */
         }
@@ -551,7 +514,8 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
     }
     else
     {
-        if (fastload) HeapFree( SystemHeap, 0, fastload );
+        if (fastload)
+	    HeapFree( SystemHeap, 0, fastload );
         GlobalFree16( hModule );
         return (HMODULE16)11;  /* invalid exe */
     }
@@ -576,7 +540,8 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
                ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
                pData ))
     {
-        if (fastload) HeapFree( SystemHeap, 0, fastload );
+        if (fastload)
+	    HeapFree( SystemHeap, 0, fastload );
         GlobalFree16( hModule );
         return (HMODULE16)11;  /* invalid exe */
     }
@@ -591,7 +556,8 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
                   ne_header.n_mod_ref_tab * sizeof(WORD),
                   pData ))
         {
-            if (fastload) HeapFree( SystemHeap, 0, fastload );
+            if (fastload)
+		HeapFree( SystemHeap, 0, fastload );
             GlobalFree16( hModule );
             return (HMODULE16)11;  /* invalid exe */
         }
@@ -606,24 +572,101 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
                ne_header.entry_tab_offset - ne_header.iname_tab_offset,
                pData ))
     {
-        if (fastload) HeapFree( SystemHeap, 0, fastload );
+        if (fastload)
+	    HeapFree( SystemHeap, 0, fastload );
         GlobalFree16( hModule );
         return (HMODULE16)11;  /* invalid exe */
     }
     pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
 
-    /* Get the entry table */
+    /* Load entry table, convert it to the optimized version used by Windows */
 
+    if ((pTempEntryTable = HeapAlloc( SystemHeap, 0, ne_header.entry_tab_length)) != NULL)
+    {
+        BYTE nr_entries, type, *s;
+
+	TRACE(module, "Converting entry table.\n");
     pModule->entry_table = (int)pData - (int)pModule;
     if (!READ( mz_header.e_lfanew + ne_header.entry_tab_offset,
-               ne_header.entry_tab_length,
-               pData ))
+                ne_header.entry_tab_length, pTempEntryTable ))
+    {
+            HeapFree( SystemHeap, 0, pTempEntryTable );
+            if (fastload)
+		HeapFree( SystemHeap, 0, fastload );
+        GlobalFree16( hModule );
+        return (HMODULE16)11;  /* invalid exe */
+    }
+
+        s = pTempEntryTable;
+        TRACE(module, "entry table: offs %04x, len %04x, entries %d\n", ne_header.entry_tab_offset, ne_header.entry_tab_length, *s);
+
+	bundle = (ET_BUNDLE *)pData;
+        TRACE(module, "first bundle: %p\n", bundle);
+	memset(bundle, 0, sizeof(ET_BUNDLE)); /* in case no entry table exists */
+	entry = (ET_ENTRY *)((BYTE *)bundle+6);
+
+	while ((nr_entries = *s++))
+        {
+	    if ((type = *s++))
+            {
+		bundle->last += nr_entries;
+                if (type == 0xff)
+                while (nr_entries--)
+                {
+                    entry->type   = type;
+                    entry->flags  = *s++;
+                    s += 2;
+                    entry->segnum = *s++;
+                    entry->offs   = *(WORD *)s; s += 2;
+		    /*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
+		    entry++;
+		}
+                else
+                while (nr_entries--)
+                {
+                    entry->type   = type;
+                    entry->flags  = *s++;
+                    entry->segnum = type;
+                    entry->offs   = *(WORD *)s; s += 2;
+		    /*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
+		    entry++;
+		}
+	    }
+            else
+            {
+                if (bundle->first == bundle->last)
+                {
+                    bundle->first += nr_entries;
+                    bundle->last += nr_entries;
+                }
+                else
+                {
+		    oldbundle = bundle;
+		    oldbundle->next = ((int)entry - (int)pModule);
+                    bundle = (ET_BUNDLE *)entry;
+                    TRACE(module, "new bundle: %p\n", bundle);
+                    bundle->first = bundle->last =
+                        oldbundle->last + nr_entries;
+                    bundle->next = 0;
+                    (BYTE *)entry += sizeof(ET_BUNDLE);
+                }
+            }
+        }
+	HeapFree( SystemHeap, 0, pTempEntryTable );
+    }
+    else
     {
-        if (fastload) HeapFree( SystemHeap, 0, fastload );
+        if (fastload)
+	    HeapFree( SystemHeap, 0, fastload );
         GlobalFree16( hModule );
         return (HMODULE16)11;  /* invalid exe */
     }
-    pData += ne_header.entry_tab_length;
+
+    pData += ne_header.entry_tab_length + sizeof(ET_BUNDLE) +
+	     2 * (ne_header.entry_tab_length - ne_header.n_mov_entry_points*6);
+
+    if ((DWORD)entry > (DWORD)pData)
+       ERR(module, "converted entry table bigger than reserved space !!!\nentry: %p, pData: %p. Please report !\n", entry, pData);
 
     /* Store the filename information */
 
@@ -636,7 +679,8 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
     /* Free the fast-load area */
 
 #undef READ
-    if (fastload) HeapFree( SystemHeap, 0, fastload );
+    if (fastload)
+	HeapFree( SystemHeap, 0, fastload );
 
     /* Get the non-resident names table */
 
@@ -792,7 +836,7 @@ static HINSTANCE16 NE_LoadFileModule( HFILE16 hFile, OFSTRUCT *ofs,
 
     pModule->count = 1;
 
-    /* Call initialization rountines for all loaded DLLs. Note that
+    /* Call initialization routines for all loaded DLLs. Note that
      * when we load implicitly linked DLLs this will be done by InitTask().
      */
 
diff --git a/loader/ne/segment.c b/loader/ne/segment.c
index 893522195097dc5f6e094da8be9a46f9a5e68276..48585cc941277e52f0e04a558485daddf0610c25 100644
--- a/loader/ne/segment.c
+++ b/loader/ne/segment.c
@@ -88,7 +88,7 @@ BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum )
     mem = GlobalLock16(pSeg->hSeg);
     if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1)
     {
- 	/* Implement self loading segments */
+ 	/* Implement self-loading segments */
  	SELFLOADHEADER *selfloadheader;
         STACK16FRAME *stack16Top;
         DWORD oldstack;
@@ -396,7 +396,7 @@ BOOL NE_LoadAllSegments( NE_MODULE *pModule )
     {
         HFILE hf;
         HFILE16 hFile16;
-        /* Handle self loading modules */
+        /* Handle self-loading modules */
         SELFLOADHEADER *selfloadheader;
         STACK16FRAME *stack16Top;
         THDB *thdb = THREAD_Current();
@@ -413,7 +413,7 @@ BOOL NE_LoadAllSegments( NE_MODULE *pModule )
         selfloadheader->EntryAddrProc = NE_GetEntryPoint(hselfload,27);
         selfloadheader->MyAlloc  = NE_GetEntryPoint(hselfload,28);
         selfloadheader->SetOwner = NE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
-        pModule->self_loading_sel = GlobalHandleToSel16(GLOBAL_Alloc(GMEM_ZEROINIT, 0xFF00, pModule->self, FALSE, FALSE, FALSE));
+        pModule->self_loading_sel = SEL(GLOBAL_Alloc(GMEM_ZEROINIT, 0xFF00, pModule->self, FALSE, FALSE, FALSE));
         oldstack = thdb->cur_stack;
         thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
                                                 0xff00 - sizeof(*stack16Top) );
@@ -453,111 +453,120 @@ BOOL NE_LoadAllSegments( NE_MODULE *pModule )
 
 
 /***********************************************************************
- *           PatchCodeHandle
+ *           NE_FixupSegmentPrologs
  *
- * Needed for self-loading modules.
+ * Fixup exported functions prologs of one segment
  */
-
-/* It does nothing */
-DWORD WINAPI PatchCodeHandle16(HANDLE16 hSel)
+void NE_FixupSegmentPrologs(NE_MODULE *pModule, WORD segnum)
 {
-    FIXME(module,"(%04x): stub.\n",hSel);
-    return (DWORD)NULL;
-}
+    SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
+    ET_BUNDLE *bundle;
+    ET_ENTRY *entry;
+    WORD dgroup, num_entries, sel = SEL(pSegTable[segnum-1].hSeg);
+    BYTE *pSeg, *pFunc;
 
+    TRACE(module, "(%d);\n", segnum);
 
-/***********************************************************************
- *           NE_FixupPrologs
- *
- * Fixup the exported functions prologs.
- */
-void NE_FixupPrologs( NE_MODULE *pModule )
+    if (pSegTable[segnum-1].flags & NE_SEGFLAGS_DATA)
 {
-    SEGTABLEENTRY *pSegTable;
-    WORD dgroup = 0;
-    WORD sel;
-    BYTE *p, *fixup_ptr, count;
-    dbg_decl_str(module, 512);
+	pSegTable[segnum-1].flags |= NE_SEGFLAGS_LOADED;
+	return;
+    }
+    if (!(dgroup = SEL(pSegTable[pModule->dgroup-1].hSeg)))
+	return;
 
-    pSegTable = NE_SEG_TABLE(pModule);
-    if (pModule->flags & NE_FFLAGS_SINGLEDATA)
-        dgroup = SEL(pSegTable[pModule->dgroup-1].hSeg);
+    pSeg = PTR_SEG_OFF_TO_LIN(sel, 0);
 
-    TRACE(module, "(%04x)\n", pModule->self );
-    p = (BYTE *)pModule + pModule->entry_table;
-    while (*p)
+    bundle = (ET_BUNDLE *)((BYTE *)pModule+pModule->entry_table);
+
+    do {
+	TRACE(module, "num_entries: %d, bundle: %p, next: %04x, pSeg: %p\n", bundle->last - bundle->first, bundle, bundle->next, pSeg);
+	if (!(num_entries = bundle->last - bundle->first))
+	    return;
+	entry = (ET_ENTRY *)((BYTE *)bundle+6);
+	while (num_entries--)
     {
-        if (p[1] == 0)  /* Unused entry */
+	    /*TRACE(module, "entry: %p, entry->segnum: %d, entry->offs: %04x\n", entry, entry->segnum, entry->offs);*/
+	    if (entry->segnum == segnum)
         {
-            p += 2;  /* Skip it */
-            continue;
-        }
-        if (p[1] == 0xfe)  /* Constant entry */
+		pFunc = ((BYTE *)pSeg+entry->offs);
+		TRACE(module, "pFunc: %p, *(DWORD *)pFunc: %08lx, num_entries: %d\n", pFunc, *(DWORD *)pFunc, num_entries);
+		if (*(pFunc+2) == 0x90)
         {
-            p += 2 + *p * 3;  /* Skip it */
-            continue;
+		    if (*(WORD *)pFunc == 0x581e) /* push ds, pop ax */
+		    {
+			TRACE(module, "patch %04x:%04x -> mov ax, ds\n", sel, entry->offs);
+			*(WORD *)pFunc = 0xd88c; /* mov ax, ds */
         }
 
-        /* Now fixup the entries of this bundle */
-        count = *p;
-        sel = p[1];
-        p += 2;
-        while (count-- > 0)
-        {
-	    dbg_reset_str(module);
-            dsprintf(module,"Flags: %04x, sel %02x ", *p, sel);
-            /* According to the output generated by TDUMP, the flags mean:
-             * 0x0001 function is exported
-	     * 0x0002 Single data (seems to occur only in DLLs)
-	     */
-	    if (sel == 0xff) { /* moveable */
-		dsprintf(module, "(%02x) o %04x", p[3], *(WORD *)(p+4) );
-		fixup_ptr = (char *)GET_SEL_BASE(SEL(pSegTable[p[3]-1].hSeg)) + *(WORD *)(p + 4);
-	    } else { /* fixed */
-		dsprintf(module, "offset %04x", *(WORD *)(p+1) );
-		fixup_ptr = (char *)GET_SEL_BASE(SEL(pSegTable[sel-1].hSeg)) + 
-		  *(WORD *)(p + 1);
-	    }
-	    TRACE(module, "%s Signature: %02x %02x %02x,ff %x\n",
-			    dbg_str(module), fixup_ptr[0], fixup_ptr[1], 
-			    fixup_ptr[2], pModule->flags );
-            if (*p & 0x0001)
-            {
-                /* Verify the signature */
-                if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
-                     || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
-                    && fixup_ptr[2] == 0x90)
-                {
-                    if (*p & 0x0002)
-                    {
-			if (pModule->flags & NE_FFLAGS_MULTIPLEDATA)
+		    if (*(WORD *)pFunc == 0xd88c)
                         {
-			    /* can this happen? */
-			    ERR(fixup, "FixupPrologs got confused\n" );
-			}
-                        else if (pModule->flags & NE_FFLAGS_SINGLEDATA)
+			if ((entry->flags & 2)) /* public data ? */
                         {
-                            *fixup_ptr = 0xb8;	/* MOV AX, */
-                            *(WORD *)(fixup_ptr+1) = dgroup;
-                        }
+			    TRACE(module, "patch %04x:%04x -> mov ax, dgroup [%04x]\n", sel, entry->offs, dgroup);
+			    *pFunc = 0xb8; /* mov ax, */
+			    *(WORD *)(pFunc+1) = dgroup;
                     }
                     else
+			if ((pModule->flags & NE_FFLAGS_MULTIPLEDATA)
+			&& (entry->flags & 1)) /* exported ? */
                     {
-			if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
-			    fixup_ptr[0] = 0x90; /* non-library: NOPs */
-			    fixup_ptr[1] = 0x90;
-			    fixup_ptr[2] = 0x90;
+			    TRACE(module, "patch %04x:%04x -> nop, nop\n", sel, entry->offs);
+			    *(WORD *)pFunc = 0x9090; /* nop, nop */
 			}
                     }
-                } else {
-		    WARN(fixup, "Unknown signature\n" );
 		}
             }
-	    else
-	      TRACE(module,"\n");
-            p += (sel == 0xff) ? 6 : 3;  
+	    entry++;
+	}
+    } while ( (bundle->next)
+	 && (bundle = ((ET_BUNDLE *)((BYTE *)pModule + bundle->next))) );
+}
+
+
+/***********************************************************************
+ *           PatchCodeHandle
+ *
+ * Needed for self-loading modules.
+ */
+DWORD WINAPI PatchCodeHandle16(HANDLE16 hSeg)
+{
+    WORD segnum;
+    WORD sel = SEL(hSeg);
+    NE_MODULE *pModule = NE_GetPtr(FarGetOwner16(sel));
+    SEGTABLEENTRY *pSegTable = NE_SEG_TABLE(pModule);
+
+    TRACE(module, "(%04x);\n", hSeg);
+
+    /* find the segment number of the module that belongs to hSeg */
+    for (segnum = 1; segnum <= pModule->seg_count; segnum++)
+    {
+	if (SEL(pSegTable[segnum-1].hSeg) == sel)
+	{
+	    NE_FixupSegmentPrologs(pModule, segnum);
+	    break;
         }
     }
+
+    return MAKELONG(hSeg, sel);
+}
+
+/***********************************************************************
+ *           NE_FixupPrologs
+ *
+ * Fixup the exported functions prologs.
+ */
+void NE_FixupPrologs( NE_MODULE *pModule )
+{
+    WORD segnum;
+
+    TRACE(module, "(%04x)\n", pModule->self );
+
+    if (pModule->flags & NE_FFLAGS_SELFLOAD)
+	NE_FixupSegmentPrologs(pModule, 1);
+    else
+    for (segnum=1; segnum <= pModule->seg_count; segnum++)
+	NE_FixupSegmentPrologs(pModule, segnum);
 }
 
 /***********************************************************************
@@ -797,23 +806,30 @@ static WORD NE_Ne2MemFlags(WORD flags)
 
 /***********************************************************************
  *           NE_AllocateSegment (WPROCS.26)
+ *
+ * MyAlloc() function for self-loading apps.
  */
 DWORD WINAPI NE_AllocateSegment( WORD wFlags, WORD wSize, WORD wElem )
 {
     WORD size = wSize << wElem;
-    HANDLE16 hMem = GlobalAlloc16( NE_Ne2MemFlags(wFlags), size);
+    HANDLE16 hMem = 0;
+
+    if (wSize || (wFlags & NE_SEGFLAGS_MOVEABLE))
+        hMem = GlobalAlloc16( NE_Ne2MemFlags(wFlags), size);
 
-    /* not data == code */
-    if (	(wFlags & NE_SEGFLAGS_EXECUTEONLY) ||
-    		!(wFlags & NE_SEGFLAGS_DATA)
-    ) {
-        WORD hSel = GlobalHandleToSel16(hMem);
+    if ( ((wFlags & 0x7) != 0x1) && /* DATA */
+         ((wFlags & 0x7) != 0x7) ) /* DATA|ALLOCATED|LOADED */
+    {
+        WORD hSel = SEL(hMem);
         WORD access = SelectorAccessRights16(hSel,0,0);
 
 	access |= 2<<2; /* SEGMENT_CODE */
 	SelectorAccessRights16(hSel,1,access);
     }
-    return MAKELONG( hMem, GlobalHandleToSel16(hMem) );
+    if (size)
+	return MAKELONG( hMem, SEL(hMem) );
+    else
+	return MAKELONG( 0, hMem );
 }
 
 
@@ -823,12 +839,17 @@ DWORD WINAPI NE_AllocateSegment( WORD wFlags, WORD wSize, WORD wElem )
 BOOL NE_CreateSegments( NE_MODULE *pModule )
 {
     SEGTABLEENTRY *pSegment;
-    int i, minsize;
+    int i, minsize, seg_count;
 
     assert( !(pModule->flags & NE_FFLAGS_WIN32) );
 
     pSegment = NE_SEG_TABLE( pModule );
-    for (i = 1; i <= pModule->seg_count; i++, pSegment++)
+
+    if (pModule->flags & NE_FFLAGS_SELFLOAD)
+        seg_count = 1;
+    else
+        seg_count = pModule->seg_count;
+    for (i = 1; i <= seg_count; i++, pSegment++)
     {
         minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
         if (i == pModule->ss) minsize += pModule->stack_size;
diff --git a/tools/build.c b/tools/build.c
index 31e10896a7923064d39135e490212e5185d983cb..30b1881e2806d01fe3900081e4663df872e54bb6 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -796,8 +796,10 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
     NE_MODULE *pModule;
     SEGTABLEENTRY *pSegment;
     OFSTRUCT *pFileInfo;
-    BYTE *pstr, *bundle;
+    BYTE *pstr;
     WORD *pword;
+    ET_BUNDLE *bundle = 0;
+    ET_ENTRY *entry = 0;
 
     /*   Module layout:
      * NE_MODULE       Module
@@ -911,7 +913,6 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
       /* Entry table */
 
     pModule->entry_table = (int)pstr - (int)pModule;
-    bundle = NULL;
     odp = OrdinalDefinitions + 1;
     for (i = 1; i <= Limit; i++, odp++)
     {
@@ -943,24 +944,25 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
             break;
         }
 
-          /* create a new bundle if necessary */
-        if (!bundle || (bundle[0] >= 254) || (bundle[1] != selector))
+	if (!bundle)
         {
-            bundle = pstr;
-            bundle[0] = 0;
-            bundle[1] = selector;
-            pstr += 2;
+	    bundle = (ET_BUNDLE *)pstr;
+	    bundle->first = 0;
+	    pstr += sizeof(ET_BUNDLE);
         }
 
-        (*bundle)++;
-        if (selector != 0)
-        {
-            *pstr++ = 1;
-            *(WORD *)pstr = odp->offset;
-            pstr += sizeof(WORD);
-        }
+	/* FIXME: is this really correct ?? */
+	entry = (ET_ENTRY *)pstr;
+	entry->type = selector;
+	entry->flags = 3; /* exported & public data */
+	entry->segnum = selector;
+	entry->offs = odp->offset;
+	pstr += sizeof(ET_ENTRY);
+
     }
     *pstr++ = 0;
+    bundle->last = i;
+    bundle->next = 0;
 
       /* Dump the module content */