DOS EMS improvements

Jukka Heinonen jhei at iki.fi
Sat Jun 22 05:04:54 CDT 2002


Here is a bunch of improvements for DOS EMS memory manager.
After these changes, Master of Magic almost works.
Unfortunately, MoM uses quite a few VGA registers that are
not emulated by Wine...


Changelog:
  Add save/restore mapping context routines.
  Add map multiple pages routine.
  Add partial implementation of hardware information query routine.
  Replace incorrect use of MapSL with PTR_REAL_TO_LIN.


Index: dlls/winedos/int67.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/int67.c,v
retrieving revision 1.3
diff -b -u -r1.3 int67.c
--- dlls/winedos/int67.c        31 May 2002 23:40:54 -0000      1.3
+++ dlls/winedos/int67.c        22 Jun 2002 09:54:44 -0000
@@ -75,6 +75,11 @@
     WORD  logical_page; /* logical page */
   } mapping[4];
 
+  struct {
+    UCHAR hindex;       /* handle number */
+    WORD  logical_page; /* logical page */
+  } mapping_save_area[EMS_MAX_HANDLES][4];
+
 } *EMS_record = 0;
 
 /**********************************************************************
@@ -147,13 +152,13 @@
 
   switch AL_reg(context) {
   case 0x00: /* get name */
-    ptr = MapSL(MAKESEGPTR(context->SegEs, DI_reg(context)));
+    ptr = PTR_REAL_TO_LIN(context->SegEs, DI_reg(context));
     memcpy(ptr, EMS_record->handle[hindex].name, 8);
     AH_reg(context) = 0;
     break;
 
   case 0x01: /* set name */
-    ptr = MapSL(MAKESEGPTR(context->SegDs, SI_reg(context)));
+    ptr = PTR_REAL_TO_LIN(context->SegDs, SI_reg(context));
     memcpy(EMS_record->handle[hindex].name, ptr, 8);
     AH_reg(context) = 0;
     break;
@@ -169,17 +174,18 @@
  *
  * Map logical page into physical page.
  */
-static void EMS_map( CONTEXT86 *context )
+static BYTE EMS_map( WORD physical_page, WORD new_hindex, WORD new_logical_page )
 {
-  int   physical_page = AL_reg(context);
-  int   new_hindex = DX_reg(context);
-  int   new_logical_page = BX_reg(context);
-
-  int   old_hindex = EMS_record->mapping[physical_page].hindex;
-  int   old_logical_page = EMS_record->mapping[physical_page].logical_page;
-
-  void *physical_address = EMS_PAGE_ADDRESS(EMS_record->frame_address,
-                                            physical_page);
+  int   old_hindex;
+  int   old_logical_page;
+  void *physical_address;
+
+  if(physical_page > 3)
+    return 0x8b; /* status: invalid physical page */
+
+  old_hindex = EMS_record->mapping[physical_page].hindex;
+  old_logical_page = EMS_record->mapping[physical_page].logical_page;
+  physical_address = EMS_PAGE_ADDRESS(EMS_record->frame_address, physical_page);
 
   /* unmap old page */
   if(old_hindex) {
@@ -192,6 +198,13 @@
   if(new_hindex && new_logical_page != 0xffff) {
     void *ptr = EMS_PAGE_ADDRESS(EMS_record->handle[new_hindex].address,
                                  new_logical_page);
+
+    if(new_hindex >= EMS_MAX_HANDLES || !EMS_record->handle[new_hindex].address)
+      return 0x83; /* status: invalid handle */
+
+    if(new_logical_page >= EMS_record->handle[new_hindex].pages)
+      return 0x8a; /* status: invalid logical page */
+
     memcpy(physical_address, ptr, EMS_PAGE_SIZE);
     EMS_record->mapping[physical_page].hindex = new_hindex;
     EMS_record->mapping[physical_page].logical_page = new_logical_page;
@@ -200,7 +213,35 @@
     EMS_record->mapping[physical_page].logical_page = 0;
   }
 
-  AH_reg(context) = 0; /* status: ok */
+  return 0; /* status: ok */
+}
+
+/**********************************************************************
+ *          EMS_map_multiple
+ *
+ * Map multiple logical pages into physical pages.
+ */
+static void EMS_map_multiple( CONTEXT86 *context )
+{
+  WORD *ptr = PTR_REAL_TO_LIN(context->SegDs, SI_reg(context));
+  BYTE  status = 0;
+  int   i;
+
+  for(i=0; i<CX_reg(context) && !status; i++, ptr += 2)
+    switch(AL_reg(context)) {
+    case 0x00:
+      status = EMS_map( ptr[1], 
+                       DX_reg(context), ptr[0] );
+      break;
+    case 0x01:
+      status = EMS_map( (ptr[1] - EMS_record->frame_selector) >> 10,
+                       DX_reg(context), ptr[0] );
+      break;
+    default:
+      status = 0x8f; /* status: undefined subfunction */    
+    }
+
+  AH_reg(context) = status;
 }
 
 /**********************************************************************
@@ -238,6 +279,48 @@
 }
 
 /**********************************************************************
+ *          EMS_save_context
+ *
+ * Save physical page mappings into handle specific save area.
+ */
+static void EMS_save_context( CONTEXT86 *context )
+{
+  WORD h = DX_reg(context);
+  int  i;
+
+  for(i=0; i<4; i++) {
+    EMS_record->mapping_save_area[h][i].hindex = EMS_record->mapping[i].hindex;
+    EMS_record->mapping_save_area[h][i].logical_page = EMS_record->mapping[i].logical_page;
+  }
+  
+  AX_reg(context) = 0; /* status: ok */
+}
+
+
+/**********************************************************************
+ *          EMS_restore_context
+ *
+ * Restore physical page mappings from handle specific save area.
+ */
+static void EMS_restore_context( CONTEXT86 *context )
+{
+  WORD handle = DX_reg(context);
+  int  i;
+
+  for(i=0; i<4; i++) {
+    int hindex       = EMS_record->mapping_save_area[handle][i].hindex;
+    int logical_page = EMS_record->mapping_save_area[handle][i].logical_page;
+
+    if(EMS_map( i, hindex, logical_page )) {
+      AX_reg(context) = 0x8e; /* status: restore of mapping context failed */
+      return;
+    }
+  }
+  
+  AX_reg(context) = 0; /* status: ok */  
+}
+
+/**********************************************************************
  *          DOSVM_Int67Handler
  *
  * Handler for interrupt 67h EMS routines.
@@ -273,7 +356,7 @@
 
   case 0x44: /* EMS - MAP MEMORY */
     EMS_init();
-    EMS_map(context);
+    AH_reg(context) = EMS_map( AL_reg(context), DX_reg(context), BX_reg(context) );
     break;
 
   case 0x45: /* EMS - RELEASE HANDLE AND MEMORY */
@@ -287,8 +370,13 @@
     break;
 
   case 0x47: /* EMS - SAVE MAPPING CONTEXT */
+    EMS_init(); 
+    EMS_save_context(context);
+    break;
+
   case 0x48: /* EMS - RESTORE MAPPING CONTEXT */
-    INT_BARF(context,0x67);
+    EMS_init();
+    EMS_restore_context(context);
     break;
 
   case 0x49: /* EMS - reserved - GET I/O PORT ADDRESSES */
@@ -305,7 +393,14 @@
   case 0x4d: /* EMS - GET PAGES FOR ALL HANDLES */
   case 0x4e: /* EMS - GET OR SET PAGE MAP */
   case 0x4f: /* EMS 4.0 - GET/SET PARTIAL PAGE MAP */
+    INT_BARF(context,0x67);
+    break;
+
   case 0x50: /* EMS 4.0 - MAP/UNMAP MULTIPLE HANDLE PAGES */
+    EMS_init();
+    EMS_map_multiple(context);
+    break;
+
   case 0x51: /* EMS 4.0 - REALLOCATE PAGES */
   case 0x52: /* EMS 4.0 - GET/SET HANDLE ATTRIBUTES */
     INT_BARF(context,0x67);
@@ -321,7 +416,22 @@
   case 0x56: /* EMS 4.0 - ALTER PAGE MAP AND CALL */
   case 0x57: /* EMS 4.0 - MOVE/EXCHANGE MEMORY REGION */
   case 0x58: /* EMS 4.0 - GET MAPPABLE PHYSICAL ADDRESS ARRAY */
+    INT_BARF(context,0x67);
+    break;
+
   case 0x59: /* EMS 4.0 - GET EXPANDED MEMORY HARDWARE INFORMATION */
+    if(AL_reg(context) == 0x01) {
+      EMS_init();
+      /* unallocated raw pages */
+      BX_reg(context) = EMS_MAX_PAGES - EMS_record->used_pages; 
+      /* total number raw pages */
+      DX_reg(context) = EMS_MAX_PAGES;
+      /* status: ok */
+      AH_reg(context) = 0;
+    } else
+      INT_BARF(context,0x67);
+    break;
+
   case 0x5a: /* EMS 4.0 - ALLOCATE STANDARD/RAW PAGES */
   case 0x5b: /* EMS 4.0 - ALTERNATE MAP REGISTER SET */
   case 0x5c: /* EMS 4.0 - PREPARE EXPANDED MEMORY HARDWARE FOR WARM BOOT */



-- 
Jukka Heinonen <http://www.iki.fi/jhei/>



More information about the wine-patches mailing list