diff --git a/kernel/entry.asm b/kernel/entry.asm
index fa0f5c6..1707401 100644
--- a/kernel/entry.asm
+++ b/kernel/entry.asm
@@ -194,10 +194,118 @@ reloc_call_int6_handler:
                 mov si,invalid_opcode_message
                 jmp short zero_message_loop        
 
+
+                ; defined in kernel.asm
+                extern _UserInt13  ; actual BIOS int13 disk handler used by kernel
+                extern _BIOSInt19  ; original int19 (reboot)
+
+; receives int 13h request, invokes original handler,
+; but passes to C routine in inthndr.c on error
+; this lets successful calls proceed with minimal overhead
+; while allowing us to handle errors, store disk change, ...
+
+            global  reloc_call_int13_handler
+reloc_call_int13_handler:
+    cli             ; disable other interrupts for now
+    stc             ; force error unless BIOS clears
+    push dx         ; store BIOS drive # for error handling usage
+
+    push ds         ; get segment of kernel DATA
+    mov  ds, [cs:_DGROUP_]
+    pushf           ; simulate int call so returns back here (flags+cs:ip on stack)
+    call far [ds:_UserInt13]
+    pop  ds          ; restore ds
+
+    ;jc   int13err   ; test if error, if not return to caller
+
+int13iret:
+    inc sp          ; clean up stack
+    inc sp
+    sti             ; ensure int's are renabled
+    retf 2          ; return to caller leaving flags asis
+
+int13err:
+    pushf           ; don't mess up flags
+
+    cmp  ah, 06h    ; disk changed
+    je   int13wrap
+
+    ; add check for other errors here, such as DMA issues
+
+    popf
+    jmp  int13iret  ; pass error asis back to user
+
+
+int13wrap:
+%IF XCPU < 186
+    push ax         ; preserve registers, setup stack frame
+    push bp
+    mov  bp, sp
+    mov  ax, 13h    ; want to push 0x13 onto stack
+    xchg ax, [bp+2] ; so restore pushed ax value and put 0x13 on stack
+    pop  bp         ; clean up stack frame (leaving just 0x13 pushed on stack)
+%ELSE                
+    push 13h        ; the 186+ way to push a constant on the stack
+%ENDIF
+
+    ; at this point stack has initial flags, called cs,ip, initial dx,
+    ; flags returned from int13 call, and value 13h
+    ; fall through to intWrapCall to invoke C handler
+    
+
+; assumes interrupt # and single word param already pushed on stack
+; pushes all registers on stack
+; calls C handler
+; restores registers (replacing value if changed by C code)
+; pops int# and param off stack
+; returns via iret
+intWrapCall:
+                    ; set up register frame
+    push ax
+    push cx
+    push dx
+    push bx
+    push bp
+    push si
+    push di
+    push ds
+    push es
+
+    cld
+
+    Protect386Registers    ; ensure 386+ registers possibly modified by kernel safe
+
+    mov ds,[cs:_DGROUP_]
+    push ds                ; mov es, ds
+    pop  es
+    extern _intXX_filter
+    call _intXX_filter
+
+    Restore386Registers    
+    
+    pop es
+    pop ds
+    pop di
+    pop si
+    pop bp
+    pop bx
+    pop dx
+    pop cx
+    pop ax
+
+    add sp, 2              ; pop int# off stack
+    popf                   ; restore flags
+    inc sp                 ; pop param off stack (without altering flags)
+    inc sp
+    retf 2                 ; iret but ignore pushed flags
+    
+; receives int 19h request to reboot
+; restores int 10,13,15,19,1b and then clears hma if in use,
+; and finally invokes original int 19h handler,
+; based on Japheth's public domain code (JEMFBHLP.ASM)
                 global reloc_call_int19_handler
 reloc_call_int19_handler:
-; from Japheth's public domain code (JEMFBHLP.ASM)
-; restores int 10,13,15,19,1b and then calls the original int 19.
+                ; restore saved interrupts to original values
                 cld
                 xor ax,ax
                 mov es,ax
@@ -217,7 +325,19 @@ nextitem:       lodsb
                 movsw
                 movsw
                 loop nextitem
-                int 19h
+
+                ; call c wrapper for any additional cleanup
+                mov  ds, [cs:_DGROUP_]
+                lds  ax,[_BIOSInt19]   ; iret calls original handler, doesn't return
+                add  sp, 4             ; so pop callers return address off stack
+                push ds                ; and replace with address of original handler
+                push ax
+                push ax                ; param, ignored
+                pushf                  ; flags, ignored
+                mov  ax, 19h           ; handler for int 19h
+                push ax
+                jmp  intWrapCall
+                ;int 19h
 
 ;
 ; Terminate the current process
@@ -241,6 +361,7 @@ reloc_call_int21_handler:
                 cmp     ah,35h
                 je      int21_func35
                 ;
+
                 ; Create the stack frame for C call.  This is done to
                 ; preserve machine state and provide a C structure for
                 ; access to registers.
@@ -276,7 +397,9 @@ int21_reentry:
                 jne     int21_1
 
 int21_user:     
+%IFNDEF WIN31SUPPORT     ; begin critical section
                 call    dos_crit_sect
+%ENDIF ; NOT WIN31SUPPORT
 
                 push    ss
                 push    bp
@@ -362,15 +485,30 @@ int21_onerrorstack:
                 jmp     short int21_exit_nodec
 
                 
-int21_2:        inc     byte [_InDOS]
+int21_2:
+%IFDEF WIN31SUPPORT     ; begin critical section
+                        ; should be called as needed, but we just
+                        ; mark the whole int21 api as critical
+                push    ax
+                mov     ax, 8001h   ; Enter Critical Section
+                int     2ah
+                pop     ax
+%ENDIF ; WIN31SUPPORT
+                inc     byte [_InDOS]
                 mov     cx,_char_api_tos
                 or      ah,ah   
                 jz      int21_3
+%IFDEF WIN31SUPPORT     ; testing, this function call crashes
+                cmp     ah,06h
+                je      int21_3
+%ENDIF ; WIN31SUPPORT
                 cmp     ah,0ch
                 jbe     int21_normalentry
 
 int21_3:
+%IFNDEF WIN31SUPPORT     ; begin critical section
                 call    dos_crit_sect
+%ENDIF ; NOT WIN31SUPPORT
                 mov     cx,_disk_api_tos
 
 int21_normalentry:
@@ -390,6 +528,17 @@ int21_normalentry:
                 call    _int21_service
 
 int21_exit:     dec     byte [_InDOS]
+%IFDEF WIN31SUPPORT     ; end critical section
+                call    dos_crit_sect  ; release all critical sections
+%if 0
+                        ; should be called as needed, but we just
+                        ; mark the whole int21 api as critical
+                push    ax
+                mov     ax, 8101h   ; Leave Critical Section
+                int     2ah
+                pop     ax
+%endif
+%ENDIF ; WIN31SUPPORT
 
                 ;
                 ; Recover registers from system call.  Registers and flags
diff --git a/kernel/init-mod.h b/kernel/init-mod.h
index 2b9868d..bf4d2e6 100644
--- a/kernel/init-mod.h
+++ b/kernel/init-mod.h
@@ -203,6 +203,7 @@ VOID ASMCFUNC init_stacks(VOID FAR * stack_base, COUNT nStacks,
 /* inthndlr.c */
 VOID ASMCFUNC FAR int0_handler(void);
 VOID ASMCFUNC FAR int6_handler(void);
+VOID ASMCFUNC FAR int13_handler(void);
 VOID ASMCFUNC FAR int19_handler(void);
 VOID ASMCFUNC FAR empty_handler(void);
 VOID ASMCFUNC FAR int20_handler(void);
@@ -253,7 +254,8 @@ extern char singleStep;
 extern char SkipAllConfig;
 extern char master_env[128];
 
-extern struct lol FAR *LoL;
+extern struct lol FAR * const LoL;
+
 
 extern struct dhdr DOSTEXTFAR ASM blk_dev; /* Block device (Disk) driver           */
 
diff --git a/kernel/int2f.asm b/kernel/int2f.asm
index be61ccd..99a975b 100644
--- a/kernel/int2f.asm
+++ b/kernel/int2f.asm
@@ -122,10 +122,14 @@ WinIdle:					; only HLT if at haltlevel 2+
 
 Int2f3:         cmp     ax,1680h                ; Win "release time slice"
                 je      WinIdle
-                cmp     ah,16h
-                je      FarTabRetn              ; other Win Hook return fast
                 cmp     ah,12h
                 je      IntDosCal               ; Dos Internal calls
+                cmp     ah,13h
+                je      IntDosCal               ; Install Int13h Hook
+                cmp     ah,16h
+                je      IntDosCal               ; Win (Multitasking) Hook
+                cmp     ah,46h
+                je      IntDosCal               ; Win Hook to avoid MCB corruption
 
                 cmp     ax,4a01h
                 je      IntDosCal               ; Dos Internal calls
@@ -135,6 +139,9 @@ Int2f3:         cmp     ax,1680h                ; Win "release time slice"
                 cmp     ax,4a33h                ; Check DOS version 7
                 jne     Check4Share
                 xor     ax,ax                   ; no undocumented shell strings
+                xor     bx,bx                   ; RBIL undoc BX = ?? (0h)
+                                                ;  " DS:DX ASCIIZ shell exe name
+                                                ;  " DS:SI SHELL= line
                 iret
 Check4Share:
 %endif
@@ -204,6 +211,28 @@ IntDosCal:
 
     cld
 
+%IFDEF WIN31SUPPORT     ; switch to local stack, no reentrancy support
+                extern  mux2F_stk_top:wrt DGROUP
+                cli
+                ; setup, initialize copy
+                mov  si, sp                ; ds:si = ss:sp (user stack)
+                mov  ax, ss
+                mov  ds, ax
+                mov  di, mux2F_stk_top-30  ; es:di = local stack-copied chunk
+                mov  es, [cs:_DGROUP_]     ; [-X == -(2*cx below+4) ]
+                mov  cx, 13                ; how many words to copy over
+                ; setup, store original stack pointer
+                mov  [es:di+28], si        ; store ss:sp
+                mov  [es:di+26], ds
+                ; actually switch to local stack
+                mov  ax, es
+                mov  ss, ax
+                mov  sp, di
+                ; copy over stack data to local stack
+                rep movsw
+                sti
+%ENDIF ; WIN31SUPPORT
+
 %if XCPU >= 386
   %ifdef WATCOM
     mov si,fs
@@ -227,6 +256,24 @@ IntDosCal:
   %endif
 %endif      
     
+%IFDEF WIN31SUPPORT     ; switch back to user stack
+                cli
+                ; setup, initialize copy
+                mov  si, sp                ; ds:si = ss:sp (local stack)
+                mov  ax, ss
+                mov  ds, ax
+                mov  di, [ds:si+28]        ; restore original ss:sp
+                mov  es, [ds:si+26]
+                mov  cx, 13                ; how many words to copy over
+                ; actually switch to user stack
+                mov  ax, es
+                mov  ss, ax
+                mov  sp, di
+                ; copy over stack data to user stack
+                rep movsw
+                sti
+%ENDIF ; WIN31SUPPORT
+    
     pop es
     pop ds
     pop di
diff --git a/kernel/inthndlr.c b/kernel/inthndlr.c
index 22677c8..39e78ad 100644
--- a/kernel/inthndlr.c
+++ b/kernel/inthndlr.c
@@ -31,6 +31,8 @@
 #include "portab.h"
 #include "globals.h"
 #include "nls.h"
+#include "win.h"
+#include "debug.h"
 
 #ifdef VERSION_STRINGS
 BYTE *RcsId =
@@ -1901,7 +1903,12 @@ struct int2f12regs {
   UWORD callerARG1;             /* used if called from INT2F/12 */
 };
 
-/* On input pr->AX==0x12xx, 0x4A01 or 0x4A02
+extern intvec BIOSInt13, UserInt13, BIOSInt19;
+
+
+/* WARNING: modifications in `r' are used outside of int2F_12_handler()
+ * On input r.AX==0x12xx, 0x4A01 or 0x4A02
+ * also handle Windows' DOS notification hooks, r.AH==0x16
  */
 VOID ASMCFUNC int2F_12_handler(struct int2f12regs FAR *pr)
 {
@@ -1931,6 +1938,252 @@ VOID ASMCFUNC int2F_12_handler(struct int2f12regs FAR *pr)
     r.BX = size;
     return;
   }
+  else if (r.AH == 0x13) /* set disk interrupt (13h) handler */
+  {
+    /* set new values for int13h calls, and must return old values */
+    register intvec tmp = UserInt13;
+    UserInt13 = MK_FP(r.ds, r.DX);            /* int13h handler to use */
+    r.ds = FP_SEG(tmp);  r.DX = FP_OFF(tmp);
+    tmp = BIOSInt13;
+    BIOSInt13 = MK_FP(r.es, r.BX);            /* int13h handler to restore on reboot */
+    r.es = FP_SEG(tmp);  r.BX = FP_OFF(tmp);
+    return;
+  }
+  else if (r.AH == 0x16) /* Window/Multitasking hooks */
+  {
+#ifdef WIN31SUPPORT  /* See "DOS Internals" or RBIL under DOSMGR for details */
+    switch (r.AL)
+    {
+      /* default: unhandled requests pass through unchanged */
+      case 0x0:          /* is Windows active */
+      case 0x0A:         /* identify Windows version */
+      {
+        /* return AX unchanged if Windows not active */
+        break;
+      } /* 0x0, 0x0A */
+      case 0x03:          /* Windows Get Instance Data */
+      {
+        /* This should only be called if AX=1607h/BX=15h is not supported. */
+        /* The data returned here corresponds directly with text entries that
+           can also be in INSTANCE.386 [which in theory means Windows could
+           be updated to support FD kernel without responding to these?].
+         */
+        DebugPrintf(("get instance data\n"));
+        break;
+      } /* 0x03 */
+      case 0x05:          /* Windows Startup Broadcast */
+      {
+        /* After receiving this call we activate compatibility changes
+           as DOS 5 does, though can wait until 0x07 subfunc 0x01
+         */
+        /* on entry:
+           DX flags, bit 0 is set(=1) for standard mode
+           DI Windows version#, major# in high byte
+           CX 0, set on exit to nonzero to fail load request
+           DS:SI is 0000:0000, for enhanced mode, at most 1 program can
+                 set to memory manager calling point to disable V86
+           ES:BX is 0000:0000, set to startup structure
+          */
+        r.CX = 0x0; /* it is ok to load Windows, give it a shot anyway :-) */
+        r.es = FP_SEG(&winStartupInfo);
+        r.BX = FP_OFF(&winStartupInfo);
+        winStartupInfo.winver = r.di;  /* match what caller says it is */
+        winInstanced = 1; /* internal flag marking Windows is active */
+        DebugPrintf(("Win startup\n"));
+        break;
+      } /* 0x05 */
+      case 0x06:          /* Windows Exit Broadcast */
+      {
+        /* can do nothing or can remove any changes made
+           specifically for Windows, must preserve DS.
+           Note: If Windows fatally exits then may not be called.
+         */
+        winInstanced = 0; /* internal flag marking Windows is NOT active */
+        DebugPrintf(("Win exit\n"));
+        break;
+      } /* 0x06 */
+      case 0x07:          /* DOSMGR Virtual Device API */
+      {
+        DebugPrintf(("Vxd:DOSMGR:%x:%x:%x:%x\n",r.AX,r.BX,r.CX,r.DX));
+        if (r.BX == 0x15) /* VxD id of "DOSMGR" */
+        {
+          switch (r.CX)
+          {
+            /* default: unhandled requests pass through unchanged */
+            case 0x00:    /* query if supported */
+            {
+              r.CX = winInstanced; /* should always be nonzero if Win is active */
+              r.DX = FP_SEG(&nul_dev); /* data segment / segment of DOS drivers */
+              r.es = FP_SEG(&winPatchTable); /* es:bx points to table of offsets */
+              r.BX = FP_OFF(&winPatchTable);
+              break;
+            }
+            case 0x01:    /* enable Win support, ie patch DOS */
+            {
+              /* DOS 5+ return with bitflags unchanged, Windows critical section
+                 needs are handled without need to patch.  If this
+                 function does not return successfully windows will
+                 attempt to do the patching itself (very bad idea).
+                 On entry BX is bitflags describing support requested,
+                 and on return DX is set to which we can support.
+                 Note: any we report as unhandled Windows will attempt
+                 to patch kernel to handle, probably not a good idea.
+                   0001h: enable critical section signals (int 2Ah functions
+                          80h/81h) to allow re-entering DOS while InDOS.
+                   0002h: allow nonzero local machine ID, ie different VMs
+                          report different values.
+                          FIXME: does this mean we need to set this or does Windows?
+                   0004h: split up binary reads to increase int 2Ah function 84h scheduling
+                          / turn Int 21h function 3Fh on STDIN into polling loop
+                   0008h: notify Windows of halting due to internal stack errors
+                   0010h: notify Windows of logical drive map change ("Insert disk X:")
+               */
+              r.BX = r.DX;    /* sure we support everything asked for, ;-) */
+              r.DX = 0xA2AB;  /* on succes DX:AX set to A2AB:B97Ch */
+              r.AX = 0xB97C;
+              /* FIXME: do we need to do anything special for FD kernel? */
+              break;
+            }
+            case 0x02:    /* disable Win support, ie remove patches */
+            {
+              /* Note: if we do anything special in 'patch DOS', undo it here.
+                 This is only called when Windows exits, can be ignored.
+               */
+              r.CX = 0;   /* for compatibility with MS-DOS 5/6 */
+              break;
+            }
+            case 0x03:    /* get internal structure sizes */
+            {
+              if (r.CX & 0x01) /* size of Current Directory Structure in bytes */
+              {
+                r.DX = 0xA2AB;   /* on succes DS:AX set to A2AB:B97Ch */
+                r.AX = 0xB97C;
+                r.CX = sizeof(struct cds);
+              }
+              else
+                r.CX = 0;      /* unknown or unsupported structure requested */
+              break;
+            }
+            case 0x04:    /* Get Instancing Exemptions */
+            {
+              /* On exit BX is bit flags denoting data that is instanced
+                 so Windows need not instance it.  DOS 5&6 fail with DX=CX=0.
+                   0001h: Current Directory Structure
+                   0002h: System File Table and device status of STDOUT
+                   0004h: device driver chain
+                   0008h: Swappable Data Area
+               */
+              r.DX = 0xA2AB;   /* on succes DX:AX set to A2AB:B97Ch */
+              r.AX = 0xB97C;
+              r.BX = 0; /* a zero here tells Windows to instance everything */
+              break;
+            }
+            case 0x05:    /* get device driver size */
+            {
+              /* On entry ES:DI points to possible device driver
+                 if is not one return with AX=BX=CX=DX=0
+                 else return BX:CX size in bytes allocated to driver
+                             and DX:AX set to A2AB:B97Ch */
+              mcb FAR *smcb = MK_PTR(mcb, (r.ES-1), 0); /* para before is possibly submcb segment */
+              /* drivers always start a seg:0 (DI==0), so if not then either 
+                 not device driver or duplicate (ie device driver file loaded
+                 is of multi-driver variety; multiple device drivers in same file,
+                 whose memory was allocated as a single chunk)
+                 Drivers don't really have a MCB, instead the DOS MCB is broken
+                 up into submcbs, which will have a type of 'D' (or 'E')
+                 So we check that this is primary segment, a device driver, and owner.
+              */
+              if (!r.DI && (smcb->m_type == 'D') && (smcb->m_psp == r.ES))
+              {
+                ULONG size = smcb->m_size * 16ul;
+                r.BX = hiword(size);
+                r.CX = loword(size);
+                r.DX = 0xA2AB;   /* on succes DX:AX set to A2AB:B97Ch */
+                r.AX = 0xB97C;
+                break;
+              }
+              r.DX = 0;   /* we aren't one so return unsupported */
+              r.AX = 0;
+              r.BX = 0;
+              r.CX = 0;
+              break;
+            }
+          }
+        }
+        DebugPrintf(("Vxd:DOSMGR:%x:%x:%x:%x\n",r.AX,r.BX,r.CX,r.DX));
+        break;
+      } /* 0x07 */
+      case 0x08:          /* Windows Init Complete Broadcast */
+      {
+        DebugPrintf(("Init complete\n"));
+        break;
+      } /* 0x08 */
+      case 0x09:          /* Windows Begin Exit Broadcast */
+      {
+        DebugPrintf(("Exit initiated\n"));
+        break;
+      } /* 0x09 */
+      case 0x0B:          /* Win TSR Identify */
+      {
+        DebugPrintf(("TSR identify request.\n"));
+        break;
+      } /* 0x0B */
+      case 0x80:          /* Win Release Time-slice */
+      {
+        /* This function is generally only called in idle loops */
+        DosIdle_hlt();
+        r.AX = 0;
+        /* DebugPrintf(("Release Time Slice\n")); */
+        break;
+      } /* 0x80 */
+      case 0x81:          /* Win3 Begin Critical Section */
+      {
+        DebugPrintf(("Begin CritSect\n"));
+        break;
+      } /* 0x81 */
+      case 0x82:          /* Win3 End Critical Section */
+      {
+        DebugPrintf(("End CritSect\n"));
+        break;
+      } /* 0x82 */
+      case 0x8F:          /* Win4 Close Awareness */
+      {
+        if (r.DH != 0x01) /* query close */
+          r.AX = 0x0;
+        /* else r.AX = 0x168F;  don't close -- continue execution */
+        break;
+      } /* 0x8F */
+      default:
+        DebugPrintf(("Win call (int 2Fh/16h): %04x %04x %04x %04x\n", r.AX, r.BX, r.CX, r.DX));
+        break;
+    }
+#endif
+    return;
+  }
+  else if (r.AH == 0x46) /* MS Windows WinOLDAP switching */
+  {
+#ifdef WIN31SUPPORT  /* See "DOS Internals" under DOSMGR or RBIL for details */
+    if (r.AL == 0x01)      /* save MCB */
+    {
+      /* To prevent corruption when dos=umb where Windows 3.0 standard
+         writes a sentinel at 9FFEh, DOS 5 will save the MCB marking
+         end of conventional memory (ie MCB following caller's PSP memory
+         block [which I assume occupies all of conventional memory] into
+         the DOS data segment.
+         Note: presumably Win3.1 uses the WinPatchTable.OffLastMCBSeg
+         when DOS ver > 5 to do this itself.
+       */
+      /* FIXME: Implement this! */
+    }
+    else if (r.AL == 0x02) /* restore MCB */
+    {
+      /* Copy the MCB we previously saved back. */
+      /* FIXME: Implement this! */
+    }
+#endif
+    return;
+  }
+  /* else (r.AH == 0x12) */
 
   switch (r.AL)
   {
@@ -2338,6 +2591,91 @@ error_carry:
 #undef r
 }
 
+
+/* how registers pushed on stack prior to calling int wrapper function,
+   when returns these are then popped off, so any changes to these
+   will effectively set the returned value in these registers
+ */
+struct intXXregs {
+#ifdef I386
+  /* preserved 386+ only registers, compiler specific */
+#endif
+  UWORD es, ds;
+  UWORD di, si, bp;
+  xreg b, d, c, a;
+  UWORD intreq;  /* which interrupt filter request for */
+  UWORD flags;   /* flags duplicated, one pushed by int call ignored */
+  xreg  param;
+  UWORD ip, cs , oflags;
+  /* top item of int caller's stack, possibly additional params */
+};
+
+
+/* additional processing for various wrapped/filtered interrupts
+   WARNING: this function also called during kernel init phase
+   -- int 13h
+   filter for BIOS int13h support, only called on int13h error
+   for ms-dos compatibility this should at minimal 
+   watch for disk-change notification and set internal status
+   (may be called multiple times in row when BIOS reports same
+   change multiple times, ie delays clearing disk change status)
+   TODO: move DMA bounday check from int25/26 to here
+   Note: use stored user (usually BIOS) hooked int13 handler
+   -- int 19h
+   clean up prior to a warm reboot 
+   for ms compatibility this should at a minimal
+   restore original (or indicated as original) BIOS int13h handler
+   and any others that may be hooked (including this one)
+   if himem loaded clear high memory area (clear vdisk signature so himem loads)
+ */
+#if defined __GNUC__ && defined  __IA16_FEATURE_ATTRIBUTE_NO_ASSUME_SS_DATA
+__attribute__((no_assume_ss_data))
+#endif
+VOID ASMCFUNC intXX_filter(struct intXXregs r)
+{
+  DebugPrintf(("int %02xh filter\n", r.intreq));
+  switch(r.intreq)
+  {
+    case 0x19:  /* reboot via bootstrap */
+    {
+      /* clear vdisk signature if kernel loaded in hma */
+      if (version_flags & 0x10)
+        fmemset(MK_FP(0xffff, 0x0010),0,512);
+      break;
+    }
+    case 0x13:  /* error with disk handler */
+    {
+      DebugPrintf(("disk error %i [ah=%x] (drive %x)\n", r.a.b.h, r.param.b.h, r.param.b.l));
+      DebugPrintf(("bx==(%x) cx==(%x) dx==(%x)\n", r.BX, r.CX, r.DX));
+      /* currently just marks floppy as changed on disk change error */
+      if ((r.a.b.h == 0x06) && (r.param.b.l < 0x80))  /* diskchange and is it a floppy? */
+      {
+        register int i;
+
+        /* mark floppy as changed */
+        for(i=0; i < blk_dev.dh_name[0]; i++)
+        {
+          ddt *pddt = getddt(i);
+          if (pddt->ddt_driveno == r.param.b.l)
+          {
+            DebugPrintf(("ddt[%i] match, flags=%04x\n", i, pddt->ddt_descflags));
+            if ((pddt->ddt_descflags & DF_CHANGELINE) && /* drive must have changeline support */
+                (pddt->ddt_descflags & DF_CURBPBLOCK)) /* and BPB not currently locked (in-use) */
+              pddt->ddt_descflags |= DF_DISKCHANGE;
+            /* or get dpb pointer from ddt and set dpbp->dpb_flags = M_CHANGED; */
+          }
+        }
+      }
+      break;
+    }
+    default:
+      DebugPrintf(("INT_ERROR!\n"));
+      break;
+  }
+}
+
+
+
 /*
  * 2000/09/04  Brian Reifsnyder
  * Modified interrupts 0x25 & 0x26 to return more accurate error codes.
diff --git a/kernel/kernel.asm b/kernel/kernel.asm
index 80748f6..88c34d7 100644
--- a/kernel/kernel.asm
+++ b/kernel/kernel.asm
@@ -320,14 +320,22 @@ segment _LOWTEXT
                 global _intvec_table
 _intvec_table:  db 10h
                 dd 0
+                ; used by int13 handler and get/set via int 2f/13h
+                global  _BIOSInt13 ; BIOS provided disk handler 
+                global  _UserInt13 ; actual disk handler used by kernel
                 db 13h
-                dd 0
+_BIOSInt13:     dd 0  
                 db 15h
                 dd 0
+                ; used for cleanup on reboot
+                global  _BIOSInt19
                 db 19h
-                dd 0
+_BIOSInt19:     dd 0
                 db 1Bh
                 dd 0
+                ; default to using BIOS provided disk handler
+                db 13h
+_UserInt13:     dd 0 
 
                 ; floppy parameter table
                 global _int1e_table
@@ -436,7 +444,7 @@ _bufloc         db      0               ; 0053 00=conv 01=HMA
 _deblock_buf    dd      0               ; 0054 deblock buffer
                 times 3 db 0            ; 0058 unknown
                 dw      0               ; 005B unknown
-                db      0, 0FFh, 0      ; 005D unknown
+                db      0, 0FFh, 0      ; 005D int24fail, memstrat, a20count
                 global _VgaSet
 _VgaSet         db      0               ; 0060 unknown
                 dw      0               ; 0061 unknown
@@ -480,7 +488,7 @@ _winStartupInfo:
                 dw instance_table,seg instance_table ; array of instance data
 instance_table: ; should include stacks, Win may auto determine SDA region
                 ; we simply include whole DOS data segment
-                dw 0, seg _DATASTART ; [SEG:OFF] address of region's base
+                dw seg _DATASTART, 0 ; [SEG:OFF] address of region's base
                 dw markEndInstanceData wrt seg _DATASTART ; size in bytes
                 dd 0 ; 0 marks end of table
                 dw 0 ; and 0 length for end of instance_table entry
@@ -508,7 +516,9 @@ _winPatchTable: ; returns offsets to various internal variables
 _firstsftt:             
                 dd -1                   ; link to next
                 dw 5                    ; count 
-        
+                times 5*59 db 0         ; reserve space for the 5 sft entries
+                db 0                    ; pad byte so next value on even boundary        
+
 ; Some references seem to indicate that this data should start at 01fbh in
 ; order to maintain 100% MS-DOS compatibility.
                 times (01fbh - ($ - DATASTART)) db 0
@@ -819,6 +829,13 @@ clk_stk_top:
                 times 128 dw 0
 int2f_stk_top:
 
+%IFDEF WIN31SUPPORT
+; mux2F private stack
+                global  mux2F_stk_top
+                times 128 dw 0
+mux2F_stk_top:
+%ENDIF ; WIN31SUPPORT
+
 ; Dynamic data:
 ; member of the DOS DATA GROUP
 ; and marks definitive end of all used data in kernel data segment
@@ -1001,6 +1018,11 @@ _int0_handler:  jmp 0:reloc_call_int0_handler
 _int6_handler:  jmp 0:reloc_call_int6_handler
                 call near forceEnableA20
 
+                global  _int13_handler
+                extern  reloc_call_int13_handler
+_int13_handler: jmp 0:reloc_call_int13_handler
+                call near forceEnableA20
+
                 global  _int19_handler
                 extern  reloc_call_int19_handler
 _int19_handler: jmp 0:reloc_call_int19_handler
diff --git a/kernel/main.c b/kernel/main.c
index e4bb6c3..6522dc6 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -68,7 +68,7 @@ __segment DosTextSeg = 0;
 
 #endif
 
-struct lol FAR *LoL = &DATASTART;
+struct lol FAR * const LoL = &DATASTART;
 
 VOID ASMCFUNC FreeDOSmain(void)
 {
@@ -112,6 +112,7 @@ VOID ASMCFUNC FreeDOSmain(void)
   /* install DOS API and other interrupt service routines, basic kernel functionality works */
   setup_int_vectors();
 
+  /* check if booting from floppy/CD */
   CheckContinueBootFromHarddisk();
 
   /* display copyright info and kernel emulation status */
@@ -247,24 +248,28 @@ STATIC void setup_int_vectors(void)
       { 0x1, FP_OFF(empty_handler) },  /* single step */
       { 0x3, FP_OFF(empty_handler) },  /* debug breakpoint */
       { 0x6, FP_OFF(int6_handler) },   /* invalid opcode */
-      { 0x19, FP_OFF(int19_handler) },
+      //{ 0x13, FP_OFF(int13_handler) }, /* BIOS disk filter */
+      { 0x19, FP_OFF(int19_handler) }, /* BIOS bootstrap loader, vdisk */
       { 0x20, FP_OFF(int20_handler) },
-      { 0x21, FP_OFF(int21_handler) },
+      { 0x21, FP_OFF(int21_handler) }, /* primary DOS API */
       { 0x22, FP_OFF(int22_handler) },
       { 0x24, FP_OFF(int24_handler) },
-      { 0x25, FP_OFF(low_int25_handler) },
+      { 0x25, FP_OFF(low_int25_handler) }, /* DOS abs read/write calls */
       { 0x26, FP_OFF(low_int26_handler) },
       { 0x27, FP_OFF(int27_handler) },
       { 0x28, FP_OFF(int28_handler) },
       { 0x2a, FP_OFF(int2a_handler) },
-      { 0x2f, FP_OFF(int2f_handler) }
+      { 0x2f, FP_OFF(int2f_handler) }  /* multiplex int */
     };
   struct vec *pvec;
   struct lowvec FAR *plvec;
   int i;
 
-  for (plvec = intvec_table; plvec < intvec_table + 5; plvec++)
+  /* save current int vectors so can restore on reboot and call original directly */
+  for (plvec = intvec_table; plvec < intvec_table + 6; plvec++)
     plvec->isv = getvec(plvec->intno);
+
+  /* install default handlers */
   for (i = 0x23; i <= 0x3f; i++)
     setvec(i, empty_handler);
   HaltCpuWhileIdle = 0;
@@ -273,7 +278,7 @@ STATIC void setup_int_vectors(void)
   pokeb(0, 0x30 * 4, 0xea);
   pokel(0, 0x30 * 4 + 1, (ULONG)cpm_entry);
 
-  /* these two are in the device driver area LOWTEXT (0x70) */
+  /* handlers for int 0x1b and 0x29 are in the device driver area LOWTEXT (0x70) */
   setvec(0x1b, got_cbreak);
   setvec(0x29, int29_handler);  /* required for printf! */
 }
diff --git a/share/makefile b/share/makefile
index f8dbbde..02e8e62 100644
--- a/share/makefile
+++ b/share/makefile
@@ -7,27 +7,36 @@ USETC2=1
 COM=1
 
 !if $(USETC2)
-TCC=d:\alt\tc201\tcc
-TLINK=d:\alt\tc201\tlink
-LIBS=d:\alt\tc201
-COPT=-c -mt -1 -Id:\alt\tc201
-LOPT=/m /s /c /t
+CCBASE=c:\tc201
+BINBASE=
 !else
-TCC=d:\alt\tc30\bin\tcc
-TLINK=d:\alt\tc30\bin\tlink
-LIBS=d:\alt\tc30\lib
+CCBASE=c:\tc30
+BINBASE=\bin
+!endif
+
 !if $(COM)
-COPT=-c -mt -1 -Id:\alt\tc30\Include
-LOPT=-m -s -c -t
+COPT=-c -mt -1 -I$(INCLUDE)
+LOPT=/m /s /c /t
 !else
-COPT=-c -ms -1 -Id:\alt\tc30\Include
-LOPT=-m -s -c
-!endif
+COPT=-c -ms -1 -I$(INCLUDE)
+LOPT=/m /s /c
 !endif
 
+CC=$(CCBASE)$(BINBASE)\tcc
+LD=$(CCBASE)$(BINBASE)\tlink
+LIBS=$(CCBASE)\lib
+INCLUDE=$(CCBASE)\include
+
 SHARE.COM: SHARE.OBJ
-	$(TLINK) $(LOPT) $(LIBS)\c0t.obj share.obj,share.com,,$(LIBS)\cs.lib
+	$(LD) $(LOPT) $(LIBS)\c0t.obj share.obj,share.com,,$(LIBS)\cs.lib
 
 SHARE.OBJ: SHARE.C    
-	$(TCC) $(COPT) share.c
+	$(CC) $(COPT) share.c
 
+CLEAN:
+	del *.obj
+	
+CLOBBER: CLEAN
+	del *.com
+	del *.exe
+	del *.map
