Release 950319

Sun Mar 19 16:30:20 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)

	* [*/*]
	Implemented a new memory mapping scheme. There's no longer a
	one-to-one mapping between 16-bit and 32-bit pointers. Please see
	file DEVELOPERS-HINTS for technical details.

	* [controls/scroll.c]
	Fixed bug when dragging mouse in horizontal scrollbars.

	* [tools/build.c] [if1632/*.spec]
	Removed support for C callback functions and for re-ordering
	of the 32-bit arguments, as these were never used. This should
	allow a more efficient callback scheme to be implemented.

	* [if1632/olecli.spec]
	Reduced the number of entries to make the 16-bit code fit in 64k.
	This limitation will soon be removed.

	* [loader/ldt.c]
	Rewrote LDT manipulation functions and implemented LDT_GetEntry().

	* [memory/global.c]
	Rewrote Global*() routines to use the new selector allocation
	mechanism.

	* [memory/local.c]
	Rewrote local heap handling to use a Windows-compatible layout
	(not really finished yet).
	Implemented TOOLHELP heap-walking routines.

	* [memory/selector.c]
	Implemented LDT manipulation API functions.

Tue Mar 14 19:50:28 EST 1995 William Magro (wmagro@tc.cornell.edu)

	* [windows/defdlg.c]
	Fixed problem where dialogs closed using the System menu 
        ('Close' item or double click on close box) would
	hang Wine.

Sun Mar 12 14:28:13 1995  Michael Patra <micky@marie.physik.TU-Berlin.DE>

	* [controls/listbox.c]
	Removed most of the statements for sending a notification message
	ListBoxDirectory(), DlgDirSelect(), DlgDirList(): Improved the
	code; Borland's standard file open dialog will work now.
	
	* [misc/main.c], [misc/file.c], [miscemu/int21.c]
	Added support for new command line option "-allowreadonly". If set
	an attempt to open a read only file in write mode will be converted 
	to opening it read only (many programs try to open all files in 
	read/write mode even if they only intend to read it - this might 
	cause a few under problems under an unix-like environment where most 
	files are read only for a "normal" user)

	* [loader/selector.c]
	GetMemoryReference(): Added support for __AHIncr and __AHShift

	* [misc/dos_fs.c]
	DOS_SimplifyPath(): This routine simplifies path names ( e.g., it
	will change "/usr///local/bin/../lib//a" to "/usr/local/lib/a" )
	match(): rewritten
	
	* [objects/text.c]
	TEXT_NextLine(): Removed a bug in the handling of LF's

	* [miscemu/int21.c]
	GetFileDateTime(): Fixed. SetFileDateTime() is still broken.

Sat Mar 11 19:46:19 1995  Martin von Loewis  <loewis@informatik.hu-berlin.de>

	* [controls/menu.c]
	ChangeMenu: defaults to MF_INSERT
	InsertMenu: allow insertion even if position is one after last item

	* [if1632/Imakefile] [if1632/compobj.spec] [if1632/relay.c]
	  [if1632/storage.spec] [include/dlls.h]
	Added stubs for STORAGE.DLL and COMPOBJ.DLL

	* [if1632/user.spec] [windows/message.c]
	InSendMessage: new function

	* [include/neexe.h][include/ne_image.c]
	NE_FixupSegment: fixed handling of additive records

	* [loader/selector.c]
	GetEntryDLLName: return NULL instead of pointer to DLL.0 if not found

	* [loader/signal.c]
	win_fault: Enter debugger on SIGFPE, too

Wed Mar  1 21:47:42 1995  Cameron Heide  (heide@ee.ualberta.ca)

        * [miscemu/int*.c]
        Various minor modifications to the clock tick counter,
        FindFirst/FindNext funcs, and DPB handling.
diff --git a/miscemu/int10.c b/miscemu/int10.c
index 8bd9545..501b183 100644
--- a/miscemu/int10.c
+++ b/miscemu/int10.c
@@ -9,14 +9,18 @@
 
 void IntBarf(int i, struct sigcontext_struct *context)
 {
-	fprintf(stdnimp, "int%x: unknown/not implemented parameters:\n", i);
-	fprintf(stdnimp, "int%x: AX %04x, BX %04x, CX %04x, DX %04x, "
+	dprintf_int(stddeb, "int%x: unknown/not implemented parameters:\n", i);
+	dprintf_int(stddeb, "int%x: AX %04x, BX %04x, CX %04x, DX %04x, "
 	       "SI %04x, DI %04x, DS %04x, ES %04x\n",
 	       i, AX, BX, CX, DX, SI, DI, DS, ES);
 }
 
 int do_int10(struct sigcontext_struct *context)
 {
+        dprintf_int(stddeb,"int10: AX %04x, BX %04x, CX %04x, DX %04x, "
+               "SI %04x, DI %04x, DS %04x, ES %04x\n",
+               AX, BX, CX, DX, SI, DI, DS, ES);
+
 	switch(AH) {
 	case 0x0f:
 		AL = 0x5b;
diff --git a/miscemu/int13.c b/miscemu/int13.c
index 294f48d..e0e62f5 100644
--- a/miscemu/int13.c
+++ b/miscemu/int13.c
@@ -9,6 +9,10 @@
 
 int do_int13(struct sigcontext_struct *context)
 {
+        dprintf_int(stddeb,"int13: AX %04x, BX %04x, CX %04x, DX %04x, "
+               "SI %04x, DI %04x, DS %04x, ES %04x\n",
+               AX, BX, CX, DX, SI, DI, DS, ES);
+
 	switch(AH) {
 	case 0x00:                            /* RESET DISK SYSTEM     */
 	case 0x04:                            /* VERIFY DISK SECTOR(S) */
diff --git a/miscemu/int1a.c b/miscemu/int1a.c
index 9cb0db0..60a29ab 100644
--- a/miscemu/int1a.c
+++ b/miscemu/int1a.c
@@ -1,4 +1,5 @@
 #include <time.h>
+#include <sys/time.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include "registers.h"
@@ -16,21 +17,27 @@
 	time_t ltime;
         DWORD ticks;
 	struct tm *bdtime;
+        struct timeval tvs;
 
-    if (debugging_relay) {
-	fprintf(stddeb,"int1A: AX %04x, BX %04x, CX %04x, DX %04x, "
+	dprintf_int(stddeb,"int1A: AX %04x, BX %04x, CX %04x, DX %04x, "
 	       "SI %04x, DI %04x, DS %04x, ES %04x\n",
 	       AX, BX, CX, DX, SI, DI, DS, ES);
-    }
 
 	switch(AH) {
 	case 0:
-                ticks = GetTickCount();
+                /* This should give us the (approximately) correct
+                 * 18.206 clock ticks per second since midnight
+                 * expected from this interrupt
+                 */
+                gettimeofday(&tvs, NULL);
+                bdtime = localtime(&tvs.tv_sec);
+                ticks = (((bdtime->tm_hour * 3600 + bdtime->tm_min * 60 +
+                        bdtime->tm_sec) * 18206) / 1000) +
+                        (tvs.tv_usec / 54927);
 		CX = ticks >> 16;
 		DX = ticks & 0x0000FFFF;
 		AX = 0;  /* No midnight rollover */
-		dprintf_int(stddeb,"int1a_00 // ltime=%ld ticks=%ld\n",
-			ltime, ticks);
+		dprintf_int(stddeb,"int1a_00 // ticks=%ld\n", ticks);
 		break;
 		
 	case 2: 
diff --git a/miscemu/int21.c b/miscemu/int21.c
index 62330ff..03afeef 100644
--- a/miscemu/int21.c
+++ b/miscemu/int21.c
@@ -18,25 +18,58 @@
 #include "dos_fs.h"
 #include "regfunc.h"
 #include "windows.h"
-#include "heap.h"
 #include "msdos.h"
 #include "registers.h"
+#include "ldt.h"
 #include "options.h"
 #include "miscemu.h"
 #include "stddebug.h"
 /* #define DEBUG_INT */
 #include "debug.h"
 
+/* Define the drive parameter block, as used by int21/1F
+ * and int21/32.  This table can be accessed through the
+ * global 'dpb' pointer, which points into the local dos
+ * heap.
+ */
+struct DPB
+{
+    BYTE drive_num;         /* 0=A, etc. */
+    BYTE unit_num;          /* Drive's unit number (?) */
+    WORD sector_size;       /* Sector size in bytes */
+    BYTE high_sector;       /* Highest sector in a cluster */
+    BYTE shift;             /* Shift count (?) */
+    WORD reserved;          /* Number of reserved sectors at start */
+    BYTE num_FAT;           /* Number of FATs */
+    WORD dir_entries;       /* Number of root dir entries */
+    WORD first_data;        /* First data sector */
+    WORD high_cluster;      /* Highest cluster number */
+    WORD sectors_in_FAT;    /* Number of sectors per FAT */
+    WORD start_dir;         /* Starting sector of first dir */
+    DWORD driver_head;      /* Address of device driver header (?) */
+    BYTE media_ID;          /* Media ID */
+    BYTE access_flag;       /* Prev. accessed flag (0=yes,0xFF=no) */
+    DWORD next;             /* Pointer to next DPB in list */
+    WORD free_search;       /* Free cluster search start */
+    WORD free_clusters;     /* Number of free clusters (0xFFFF=unknown) */
+};
+
 WORD ExtendedError, CodePage = 437;
 BYTE ErrorClass, Action, ErrorLocus;
 BYTE *dta;
+DWORD dtasegptr;
+struct DPB *dpb;
+DWORD dpbsegptr;
 
 struct DosHeap {
 	BYTE dta[256];
 	BYTE InDosFlag;
+        BYTE mediaID;
 	BYTE biosdate[8];
+        struct DPB dpb;
 };
 static struct DosHeap *heap;
+static WORD DosHeapHandle;
 
 WORD sharing_retries = 3;      /* number of retries at sharing violation */
 WORD sharing_pause = 1;        /* pause between retries */
@@ -87,22 +120,12 @@
 			Error (FileExists, EC_Exists, EL_Disk);
 			break;				
 		default:
-			fprintf(stderr, "int21: unknown errno %d!\n", errno);
+			dprintf_int(stddeb, "int21: unknown errno %d!\n", errno);
 			Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
 			break;
 	}
 }
 
-/*
-static void Barf(struct sigcontext_struct *context)
-{
-	fprintf(stdnimp, "int21: unknown/not implemented parameters:\n");
-	fprintf(stdnimp, "int21: AX %04x, BX %04x, CX %04x, DX %04x, "
-	       "SI %04x, DI %04x, DS %04x, ES %04x\n",
-	       AX, BX, CX, DX, SI, DI, DS, ES);
-}
-*/
-
 void ChopOffWhiteSpace(char *string)
 {
 	int length;
@@ -180,7 +203,6 @@
 static void GetDriveAllocInfo(struct sigcontext_struct *context)
 {
 	long size, available;
-	BYTE mediaID;
 	
 	if (!DOS_ValidDrive(DL)) {
 		AX = 4;
@@ -200,10 +222,10 @@
 	ECX = 512;
 	EDX = (size / (CX * AX));
 
-	mediaID = 0xf0;
+	heap->mediaID = 0xf0;
 
-	DS = segment(mediaID);
-	BX = offset(mediaID);	
+	DS = DosHeapHandle;
+	BX = (int)&heap->mediaID - (int)heap;
 	Error (0,0,0);
 }
 
@@ -213,11 +235,46 @@
 	GetDriveAllocInfo(context);
 }
 
-static void GetDrivePB(struct sigcontext_struct *context)
+static void GetDrivePB(struct sigcontext_struct *context, int drive)
 {
-	Error (InvalidDrive, EC_MediaError, EL_Disk);
-	AX = 0x00ff;
-		/* I'm sorry but I only got networked drives :-) */
+        if(!DOS_ValidDrive(drive))
+        {
+	        Error (InvalidDrive, EC_MediaError, EL_Disk);
+                AX = 0x00ff;
+        }
+        else
+        {
+                dprintf_int(stddeb, "int21: GetDrivePB not fully implemented.\n");
+
+                /* FIXME: I have no idea what a lot of this information should
+                 * say or whether it even really matters since we're not allowing
+                 * direct block access.  However, some programs seem to depend on
+                 * getting at least _something_ back from here.  The 'next' pointer
+                 * does worry me, though.  Should we have a complete table of
+                 * separate DPBs per drive?  Probably, but I'm lazy. :-)  -CH
+                 */
+                dpb->drive_num = dpb->unit_num = drive;    /* The same? */
+                dpb->sector_size = 512;
+                dpb->high_sector = 1;
+                dpb->shift = 0;
+                dpb->reserved = 0;
+                dpb->num_FAT = 1;
+                dpb->dir_entries = 2;
+                dpb->first_data = 2;
+                dpb->high_cluster = 1023;
+                dpb->sectors_in_FAT = 1;
+                dpb->start_dir = 1;
+                dpb->driver_head = 0;
+                dpb->media_ID = (drive > 1) ? 0xF8 : 0xF0;
+                dpb->access_flag = 0;
+                dpb->next = 0;
+                dpb->free_search = 0;
+                dpb->free_clusters = 0xFFFF;    /* unknown */
+
+                AL = 0x00;
+                DS = SELECTOROF(dpbsegptr);
+                BX = OFFSETOF(dpbsegptr);
+        }
 }
 
 static void ReadFile(struct sigcontext_struct *context)
@@ -233,7 +290,7 @@
 		return;
 	}
 
-	ptr = SAFEMAKEPTR (DS,DX);
+	ptr = PTR_SEG_OFF_TO_LIN (DS,DX);
 	if (BX == 0) {
 		*ptr = EOF;
 		Error (0,0,0);
@@ -259,7 +316,7 @@
 	char *ptr;
 	int x,size;
 	
-	ptr = SAFEMAKEPTR (DS,DX);
+	ptr = PTR_SEG_OFF_TO_LIN (DS,DX);
 	
 	if (BX == 0) {
 		Error (InvalidHandle, EC_Unknown, EL_Unknown);
@@ -329,7 +386,8 @@
 		case 0:
 		case 1:
 		case 2:
-			DX = 0x80d3;
+			DX = 0x80d0 + (1 << BX);
+                        ResetCflag;
 			break;
 
 		default:
@@ -353,7 +411,7 @@
 
 static void ioctlGenericBlkDevReq(struct sigcontext_struct *context)
 {
-	BYTE *dataptr = SAFEMAKEPTR(DS, DX);
+	BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS, DX);
 	int drive;
 
 	if (BL == 0)
@@ -434,7 +492,7 @@
 {
 	int handle;
 
-	if ((handle = open(DOS_GetUnixFileName( SAFEMAKEPTR(DS,DX)), 
+	if ((handle = open(DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS,DX)), 
            O_CREAT | O_TRUNC | O_RDWR )) == -1) {
 		errno_to_doserr();
 		AL = ExtendedError;
@@ -467,11 +525,19 @@
 	    break;
 	}
 
-	if ((handle = open(DOS_GetUnixFileName(SAFEMAKEPTR(DS,DX)), mode)) == -1) {
-		errno_to_doserr();
-		AL = ExtendedError;
-		SetCflag;
-		return;
+	if ((handle = open(DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS,DX)),
+                           mode)) == -1)
+        {
+            if( Options.allowReadOnly )
+                handle = open( DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS,DX)),
+                               O_RDONLY );
+            if( handle == -1 )
+            {
+                errno_to_doserr();
+                AL = ExtendedError;
+                SetCflag;
+                return;
+            }
 	}		
 
         switch (AX & 0x0070)
@@ -482,9 +548,9 @@
 	    break;
 
 	  case 0x30:    /* DENYREAD */
-	    dprintf_int(stdnimp,
+	    dprintf_int(stddeb,
 	      "OpenExistingFile (%s): DENYREAD changed to DENYALL\n",
-	      (char *)SAFEMAKEPTR(DS,DX));
+	      (char *)PTR_SEG_OFF_TO_LIN(DS,DX));
 	  case 0x10:    /* DENYALL */  
 	    lock = LOCK_EX;
 	    break;
@@ -548,10 +614,10 @@
 	char *newname, *oldname;
 
 	dprintf_int(stddeb,"int21: renaming %s to %s\n",
-			(char *)SAFEMAKEPTR(DS,DX), (char *)SAFEMAKEPTR(ES,DI) );
+			(char *)PTR_SEG_OFF_TO_LIN(DS,DX), (char *)PTR_SEG_OFF_TO_LIN(ES,DI) );
 	
-	oldname = DOS_GetUnixFileName( SAFEMAKEPTR(DS,DX) );
-	newname = DOS_GetUnixFileName( SAFEMAKEPTR(ES,DI) );
+	oldname = DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS,DX) );
+	newname = DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(ES,DI) );
 
 	rename( oldname, newname);
 	ResetCflag;
@@ -562,9 +628,9 @@
 {
 	char *dirname;
 
-	dprintf_int(stddeb,"int21: makedir %s\n", (char *)SAFEMAKEPTR(DS,DX) );
+	dprintf_int(stddeb,"int21: makedir %s\n", (char *)PTR_SEG_OFF_TO_LIN(DS,DX) );
 	
-	if ((dirname = DOS_GetUnixFileName( SAFEMAKEPTR(DS,DX) ))== NULL) {
+	if ((dirname = DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS,DX) ))== NULL) {
 		AL = CanNotMakeDir;
 		SetCflag;
 		return;
@@ -581,7 +647,7 @@
 static void ChangeDir(struct sigcontext_struct *context)
 {
 	int drive;
-	char *dirname = SAFEMAKEPTR(DS,DX);
+	char *dirname = PTR_SEG_OFF_TO_LIN(DS,DX);
 	drive = DOS_GetDefaultDrive();
 	dprintf_int(stddeb,"int21: changedir %s\n", dirname);
 	if (dirname != NULL && dirname[1] == ':') {
@@ -599,9 +665,9 @@
 {
 	char *dirname;
 
-	dprintf_int(stddeb,"int21: removedir %s\n", (char *)SAFEMAKEPTR(DS,DX) );
+	dprintf_int(stddeb,"int21: removedir %s\n", (char *)PTR_SEG_OFF_TO_LIN(DS,DX) );
 
-	if ((dirname = DOS_GetUnixFileName( SAFEMAKEPTR(DS,DX) ))== NULL) {
+	if ((dirname = DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS,DX) ))== NULL) {
 		AL = CanNotMakeDir;
 		SetCflag;
 		return;
@@ -622,14 +688,15 @@
 
 static void ExecProgram(struct sigcontext_struct *context)
 {
-	execl("wine", DOS_GetUnixFileName( SAFEMAKEPTR(DS,DX)) );
+	execl("wine", DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS,DX)) );
 }
 
 static void FindNext(struct sigcontext_struct *context)
 {
 	struct dosdirent *dp;
+        struct tm *t;
 	
-        memcpy(&dp, dta+0x0d, sizeof(dp));
+        memcpy(&dp, dta+0x11, sizeof(dp));
 
 	do {
 		if ((dp = DOS_readdir(dp)) == NULL) {
@@ -639,24 +706,33 @@
 			return;
 		}
 	} /* while (*(dta + 0x0c) != dp->attribute);*/
-       while ( ( dp->search_attribute & dp->attribute) != dp->attribute);
+        while ( ( dp->search_attribute & dp->attribute) != dp->attribute);
 	
   	*(dta + 0x15) = dp->attribute;
-	setword(&dta[0x16], 0x1234); /* time */
-	setword(&dta[0x18], 0x1234); /* date */
+        setword(&dta[0x0d], dp->entnum);
+
+        t = localtime(&(dp->filetime));
+	setword(&dta[0x16], (t->tm_hour << 11) + (t->tm_min << 5) +
+                (t->tm_sec / 2)); /* time */
+	setword(&dta[0x18], ((t->tm_year - 80) << 9) + (t->tm_mon << 5) +
+                (t->tm_mday)); /* date */
 	setdword(&dta[0x1a], dp->filesize);
 	strncpy(dta + 0x1e, dp->filename, 13);
 
 	AL = 0;
 	ResetCflag;
+
+        dprintf_int(stddeb, "int21: FindNext -- (%s) index=%d size=%ld\n", dp->filename, dp->entnum, dp->filesize);
 	return;
 }
 
 static void FindFirst(struct sigcontext_struct *context)
 {
-	BYTE drive, *path = SAFEMAKEPTR(DS, DX);
+	BYTE drive, *path = PTR_SEG_OFF_TO_LIN(DS, DX);
 	struct dosdirent *dp;
 
+        dprintf_int(stddeb, "int21: FindFirst path = %s\n", path);
+
 	if ((*path)&&(path[1] == ':')) {
 		drive = (islower(*path) ? toupper(*path) : *path) - 'A';
 
@@ -692,23 +768,16 @@
 	}
 
 	dp->search_attribute = ECX & (FA_LABEL | FA_DIREC);
-	memcpy(dta + 0x0d, &dp, sizeof(dp));
+	memcpy(dta + 0x11, &dp, sizeof(dp));
 	FindNext(context);
 }
 
 static void GetFileDateTime(struct sigcontext_struct *context)
 {
-	char *filename;
 	struct stat filestat;
 	struct tm *now;
 
-	if ((filename = DOS_GetUnixFileName( SAFEMAKEPTR(DS,DX) ))== NULL) {
-		AL = FileNotFound;
-		SetCflag;
-		return;
-	}
-	stat(filename, &filestat);
-	 	
+        fstat( BX, &filestat );	
 	now = localtime (&filestat.st_mtime);
 	
 	CX = ((now->tm_hour * 0x2000) + (now->tm_min * 0x20) + now->tm_sec/2);
@@ -722,7 +791,9 @@
 	char *filename;
 	struct utimbuf filetime;
 	
-	filename = DOS_GetUnixFileName( SAFEMAKEPTR(DS,DX) );
+        /* FIXME: Argument isn't the name of the file in DS:DX,
+           but the file handle in BX */
+	filename = DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS,DX) );
 
 	filetime.actime = 0L;
 	filetime.modtime = filetime.actime;
@@ -748,7 +819,7 @@
 		return;
 	}
 
-	strcpy(SAFEMAKEPTR(DS,DX), temp);
+	strcpy(PTR_SEG_OFF_TO_LIN(DS,DX), temp);
 	
 	AX = handle;
 	ResetCflag;
@@ -758,7 +829,7 @@
 {
 	int handle;
 	
-	if ((handle = open(DOS_GetUnixFileName( SAFEMAKEPTR(DS,DX) ), O_CREAT | O_EXCL | O_RDWR)) == -1) {
+	if ((handle = open(DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS,DX) ), O_CREAT | O_EXCL | O_RDWR)) == -1) {
 		AL = WriteProtected;
 		SetCflag;
 		return;
@@ -783,14 +854,14 @@
 		return;
 	}
 
-	strcpy(SAFEMAKEPTR(DS,SI), DOS_GetCurrentDir(drive) );
+	strcpy(PTR_SEG_OFF_TO_LIN(DS,SI), DOS_GetCurrentDir(drive) );
 	ResetCflag;
 }
 
 static void GetDiskSerialNumber(struct sigcontext_struct *context)
 {
 	int drive;
-	BYTE *dataptr = SAFEMAKEPTR(DS, DX);
+	BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS, DX);
 	DWORD serialnumber;
 	
 	if (BL == 0)
@@ -818,7 +889,7 @@
 static void SetDiskSerialNumber(struct sigcontext_struct *context)
 {
 	int drive;
-	BYTE *dataptr = SAFEMAKEPTR(DS, DX);
+	BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS, DX);
 	DWORD serialnumber;
 
 	if (BL == 0)
@@ -858,7 +929,7 @@
 
 static void FindFirstFCB(struct sigcontext_struct *context)
 {
-	BYTE *fcb = SAFEMAKEPTR(DS, DX);
+	BYTE *fcb = PTR_SEG_OFF_TO_LIN(DS, DX);
 	struct fcb *standard_fcb;
 	struct fcb *output_fcb;
 	int drive;
@@ -925,7 +996,7 @@
 
 static void DeleteFileFCB(struct sigcontext_struct *context)
 {
-	BYTE *fcb = SAFEMAKEPTR(DS, DX);
+	BYTE *fcb = PTR_SEG_OFF_TO_LIN(DS, DX);
 	int drive;
 	struct dosdirent *dp;
 	char temp[256], *ptr;
@@ -967,7 +1038,7 @@
 
 static void RenameFileFCB(struct sigcontext_struct *context)
 {
-	BYTE *fcb = SAFEMAKEPTR(DS, DX);
+	BYTE *fcb = PTR_SEG_OFF_TO_LIN(DS, DX);
 	int drive;
 	struct dosdirent *dp;
 	char temp[256], oldname[256], newname[256], *oldnameptr, *newnameptr;
@@ -1067,7 +1138,7 @@
 
 static void GetFileAttribute (struct sigcontext_struct * context)
 {
-  char *filename = SAFEMAKEPTR (DS,DX);
+  char *filename = PTR_SEG_OFF_TO_LIN (DS,DX);
   struct stat s;
   int res,cx; 
 
@@ -1097,12 +1168,9 @@
 
 int do_int21(struct sigcontext_struct * context)
 {
-    if (debugging_relay)
-    {
-	fprintf(stddeb,"int21: AX %04x, BX %04x, CX %04x, DX %04x, "
-	       "SI %04x, DI %04x, DS %04x, ES %04x\n",
-	       AX, BX, CX, DX, SI, DI, DS, ES);
-    }
+    dprintf_int(stddeb,"int21: AX %04x, BX %04x, CX %04x, DX %04x, "
+           "SI %04x, DI %04x, DS %04x, ES %04x\n",
+           AX, BX, CX, DX, SI, DI, DS, ES);
 
     if (AH == 0x59) 
     {
@@ -1199,7 +1267,8 @@
 	    break;
 
 	  case 0x1a: /* SET DISK TRANSFER AREA ADDRESS */
-            dta = SAFEMAKEPTR(DS, DX);
+            dtasegptr = MAKELONG( DX, DS );
+            dta = PTR_SEG_TO_LIN(dtasegptr);
             break;
 
 	  case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */
@@ -1211,12 +1280,12 @@
 	    break;
 
 	  case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */
-	    GetDrivePB(context);
+	    GetDrivePB(context, DOS_GetDefaultDrive());
 	    break;
 		
 	  case 0x25: /* SET INTERRUPT VECTOR */
 	    /* Ignore any attempt to set a segment vector */
- 		dprintf_int(stdnimp,
+ 		dprintf_int(stddeb,
 			"int21: set interrupt vector %2x (%04x:%04x)\n",
 			AL, DS, DX);
             break;
@@ -1230,8 +1299,8 @@
 	    break;
 
 	  case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */
-            ES = segment(dta);
-            BX = offset(dta);
+            ES = SELECTOROF(dtasegptr);
+            BX = OFFSETOF(dtasegptr);
             break;
             
 	  case 0x30: /* GET DOS VERSION */
@@ -1245,7 +1314,7 @@
 	    break;
 
 	  case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */
-	    GetDrivePB(context);
+	    GetDrivePB(context, (DL == 0) ? (DOS_GetDefaultDrive()) : (DL-1));
 	    break;
 
 	  case 0x33: /* MULTIPLEXED */
@@ -1279,14 +1348,14 @@
 	    break;	
 	    
 	  case 0x34: /* GET ADDRESS OF INDOS FLAG */
-		ES = segment(heap->InDosFlag);
-		BX = offset(heap->InDosFlag);
+		ES = DosHeapHandle;
+		BX = (int)&heap->InDosFlag - (int)heap;
 	    break;
 
 	  case 0x35: /* GET INTERRUPT VECTOR */
 	    /* Return a NULL segment selector - this will bomb, 
 	    		if anyone ever tries to use it */
-	    dprintf_int(stdnimp, "int21: get interrupt vector %2x\n",
+	    dprintf_int(stddeb, "int21: get interrupt vector %2x\n",
 		AX & 0xff);
 	    ES = 0;
 	    BX = 0;
@@ -1334,7 +1403,7 @@
 	    break;
 	
 	  case 0x41: /* "UNLINK" - DELETE FILE */
-		if (unlink( DOS_GetUnixFileName( SAFEMAKEPTR(DS,DX)) ) == -1) {
+		if (unlink( DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS,DX)) ) == -1) {
 			errno_to_doserr();
 			AL = ExtendedError;
 			SetCflag;
@@ -1366,6 +1435,11 @@
               case 0x00:
                 ioctlGetDeviceInfo(context);
 		break;
+
+              case 0x08:   /* Check if drive is removable. */
+                EAX = (EAX & 0xFFFF0000) | 0x0001;   /* Nope, not removable. */
+                ResetCflag;
+                break;
 		   
 	      case 0x09:   /* CHECK IF BLOCK DEVICE REMOTE */
 		EDX = (EDX & 0xffff0000) | (1<<9) | (1<<12) | (1<<15);
@@ -1388,6 +1462,13 @@
               case 0x0d:
                 ioctlGenericBlkDevReq(context);
                 break;
+
+              case 0x0F:   /* Set logical drive mapping */
+                /* FIXME: Not implemented at the moment, always returns error
+                 */
+                EAX = (EAX & 0xFFFF0000) | 0x0001; /* invalid function */
+                SetCflag;
+                break;
                 
 	      default:
                 IntBarf(0x21, context);
@@ -1524,7 +1605,7 @@
 	    break;
 
 	  case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */
-		strncpy(SAFEMAKEPTR(ES,DI), SAFEMAKEPTR(DS,SI), strlen(SAFEMAKEPTR(DS,SI)) & 0x7f);
+		strncpy(PTR_SEG_OFF_TO_LIN(ES,DI), PTR_SEG_OFF_TO_LIN(DS,SI), strlen(PTR_SEG_OFF_TO_LIN(DS,SI)) & 0x7f);
 		ResetCflag;
 	    break;
 
@@ -1596,19 +1677,17 @@
 
 void INT21_Init(void)
 {
-	int handle;
-	MDESC *DosHeapDesc;
+    if ((DosHeapHandle = GlobalAlloc(GMEM_FIXED,sizeof(struct DosHeap))) == 0)
+    {
+        fprintf( stderr, "INT21_Init: Out of memory\n");
+        exit(1);
+    }
+    heap = (struct DosHeap *) GlobalLock(DosHeapHandle);
 
-	if ((handle = GlobalAlloc(GMEM_FIXED,sizeof(struct DosHeap))) == 0)
-        {
-            fprintf( stderr, "INT21_Init: Out of memory\n");
-            exit(1);
-        }
-
-	heap = (struct DosHeap *) GlobalLock(handle);
-	HEAP_Init(&DosHeapDesc, heap, sizeof(struct DosHeap));
-
-	dta = heap->dta;
-	heap->InDosFlag = 0;
-	strcpy(heap->biosdate, "01/01/80");
+    dta = heap->dta;
+    dpb = &heap->dpb;
+    dtasegptr = MAKELONG( 0, DosHeapHandle );
+    dpbsegptr = MAKELONG( (int)&heap->dpb - (int)heap, DosHeapHandle );
+    heap->InDosFlag = 0;
+    strcpy(heap->biosdate, "01/01/80");
 }
diff --git a/miscemu/int25.c b/miscemu/int25.c
index 38c306d..2f5eaaf 100644
--- a/miscemu/int25.c
+++ b/miscemu/int25.c
@@ -3,7 +3,7 @@
 #include <string.h>
 #include "registers.h"
 #include "msdos.h"
-#include "segmem.h"
+#include "ldt.h"
 #include "wine.h"
 #include "miscemu.h"
 #include "stddebug.h"
@@ -12,13 +12,13 @@
 
 int do_int25(struct sigcontext_struct *context)
 {
-	BYTE *dataptr = SAFEMAKEPTR(DS, BX);
+	BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS, BX);
 	DWORD begin, length;
 
 	if (CX == 0xffff) {
 		begin = getdword(dataptr);
 		length = getword(&dataptr[4]);
-		dataptr = (BYTE *) getdword(&dataptr[6]);
+		dataptr = (BYTE *) PTR_SEG_TO_LIN(getdword(&dataptr[6]));
 			
 	} else {
 		begin = DX;
@@ -39,7 +39,7 @@
 
 	/* push flags on stack */
 	SP -= sizeof(WORD);
-	setword(SAFEMAKEPTR(SS,SP), (WORD) EFL);
+	setword(PTR_SEG_OFF_TO_LIN(SS,SP), (WORD) EFL);
 
 	return 1;
 }
diff --git a/miscemu/int26.c b/miscemu/int26.c
index c642f4c..051a4de 100644
--- a/miscemu/int26.c
+++ b/miscemu/int26.c
@@ -2,7 +2,7 @@
 #include <stdlib.h>
 #include "registers.h"
 #include "msdos.h"
-#include "segmem.h"
+#include "ldt.h"
 #include "wine.h"
 #include "miscemu.h"
 #include "stddebug.h"
@@ -11,13 +11,13 @@
 
 int do_int26(struct sigcontext_struct *context)
 {
-	BYTE *dataptr = SAFEMAKEPTR(DS, BX);
+	BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS, BX);
 	DWORD begin, length;
 
 	if (CX == 0xffff) {
 		begin = getdword(dataptr);
 		length = getword(&dataptr[4]);
-		dataptr = (BYTE *) getdword(&dataptr[6]);
+		dataptr = (BYTE *) PTR_SEG_TO_LIN(getdword(&dataptr[6]));
 			
 	} else {
 		begin = DX;
@@ -31,7 +31,7 @@
 
 	/* push flags on stack */
 	SP -= sizeof(WORD);
-	setword(SAFEMAKEPTR(SS,SP), (WORD) EFL);
+	setword(PTR_SEG_OFF_TO_LIN(SS,SP), (WORD) EFL);
 
 	return 1;
 }
diff --git a/miscemu/int2f.c b/miscemu/int2f.c
index 25d9acd..106d110 100644
--- a/miscemu/int2f.c
+++ b/miscemu/int2f.c
@@ -11,6 +11,10 @@
 
 int do_int2f(struct sigcontext_struct *context)
 {
+        dprintf_int(stddeb,"int2f: AX %04x, BX %04x, CX %04x, DX %04x, "
+               "SI %04x, DI %04x, DS %04x, ES %04x\n",
+               AX, BX, CX, DX, SI, DI, DS, ES);
+
 	switch((context->sc_eax >> 8) & 0xff)
 	{
 	case 0x10: /* share is installed */
diff --git a/miscemu/kernel.c b/miscemu/kernel.c
index 70b3283..8f24c72 100644
--- a/miscemu/kernel.c
+++ b/miscemu/kernel.c
@@ -14,36 +14,6 @@
 extern unsigned short WIN_StackSize;
 
 /**********************************************************************
- *					KERNEL_LockSegment
- */
-int
-KERNEL_LockSegment(int segment)
-{
-    if (segment == -1)
-	segment = pStack16Frame->ds;
-
-    if (debugging_relay)
-	fprintf(stddeb,"LockSegment: segment %x\n", segment);
-
-    return segment;
-}
-
-/**********************************************************************
- *					KERNEL_UnlockSegment
- */
-int
-KERNEL_UnlockSegment(int segment)
-{
-    if (segment == -1)
-	segment = pStack16Frame->ds;
-
-    if (debugging_relay)
-    	fprintf(stddeb,"UnlockSegment: segment %x\n", segment);
-
-    return segment;
-}
-
-/**********************************************************************
  *					KERNEL_InitTask
  */
 void KERNEL_InitTask(void)