This patch moves simple int21 functions to winedos and also moves int08 stub and LOL to upper memory. The idea is to not use conventional memory unless it is absolutely necessary. Next patch probably moves collate table to upper memory which should be the final upper memory fix needed to enable >600k conventional memory. After that I probably concentrate on DPMI32 and on making 16-bit winedos dll unnecessary (these two issues are closely coupled). Changelog: Move int08 stub and LOL to upper memory. Move simple int21 functions to winedos. Index: dlls/winedos/int21.c =================================================================== RCS file: /home/wine/wine/dlls/winedos/int21.c,v retrieving revision 1.17 diff -u -r1.17 int21.c --- dlls/winedos/int21.c 3 Dec 2002 19:11:50 -0000 1.17 +++ dlls/winedos/int21.c 6 Dec 2002 21:53:46 -0000 @@ -45,7 +45,29 @@ /*********************************************************************** + * INT21_GetPSP + * + * Handler for functions 0x51 and 0x62. + */ +static void INT21_GetPSP( CONTEXT86 *context ) +{ + TRACE( "GET CURRENT PSP ADDRESS (%02x)\n", AH_reg(context) ); + + /* + * FIXME: should we return the original DOS PSP upon + * Windows startup ? + */ + if (!ISV86(context) && DOSVM_IsWin16()) + SET_BX( context, LOWORD(GetCurrentPDB16()) ); + else + SET_BX( context, DOSVM_psp ); +} + + +/*********************************************************************** * INT21_Ioctl + * + * Handler for function 0x44. */ static void INT21_Ioctl( CONTEXT86 *context ) { @@ -347,7 +369,6 @@ case 0x0d: /* DISK BUFFER FLUSH */ TRACE("DISK BUFFER FLUSH ignored\n"); - RESET_CFLAG( context ); /* dos 6+ only */ break; case 0x0e: /* SELECT DEFAULT DRIVE */ @@ -410,7 +431,7 @@ TRACE("SET INTERRUPT VECTOR 0x%02x\n",AL_reg(context)); { FARPROC16 ptr = (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context) ); - if (DOSVM_IsWin16()) + if (!ISV86(context) && DOSVM_IsWin16()) DOSVM_SetPMHandler16( AL_reg(context), ptr ); else DOSVM_SetRMHandler( AL_reg(context), ptr ); @@ -424,10 +445,21 @@ break; case 0x29: /* PARSE FILENAME INTO FCB */ - case 0x2a: /* GET SYSTEM DATE */ INT_Int21Handler( context ); break; + case 0x2a: /* GET SYSTEM DATE */ + TRACE( "GET SYSTEM DATE\n" ); + { + SYSTEMTIME systime; + GetLocalTime( &systime ); + SET_CX( context, systime.wYear ); + SET_DH( context, systime.wMonth ); + SET_DL( context, systime.wDay ); + SET_AL( context, systime.wDayOfWeek ); + } + break; + case 0x2b: /* SET SYSTEM DATE */ FIXME("SetSystemDate(%02d/%02d/%04d): not allowed\n", DL_reg(context), DH_reg(context), CX_reg(context) ); @@ -435,7 +467,15 @@ break; case 0x2c: /* GET SYSTEM TIME */ - INT_Int21Handler( context ); + TRACE( "GET SYSTEM TIME\n" ); + { + SYSTEMTIME systime; + GetLocalTime( &systime ); + SET_CL( context, systime.wHour ); + SET_CH( context, systime.wMinute ); + SET_DH( context, systime.wSecond ); + SET_DL( context, systime.wMilliseconds / 10 ); + } break; case 0x2d: /* SET SYSTEM TIME */ @@ -469,7 +509,7 @@ TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context)); { FARPROC16 addr; - if (DOSVM_IsWin16()) + if (!ISV86(context) && DOSVM_IsWin16()) addr = DOSVM_GetPMHandler16( AL_reg(context) ); else addr = DOSVM_GetRMHandler( AL_reg(context) ); @@ -527,8 +567,59 @@ case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */ case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */ case 0x47: /* "CWD" - GET CURRENT DIRECTORY */ + INT_Int21Handler( context ); + break; + case 0x48: /* ALLOCATE MEMORY */ + TRACE( "ALLOCATE MEMORY for %d paragraphs\n", BX_reg(context) ); + { + WORD selector = 0; + DWORD bytes = (DWORD)BX_reg(context) << 4; + + if (!ISV86(context) && DOSVM_IsWin16()) + { + DWORD rv = GlobalDOSAlloc16( bytes ); + selector = LOWORD( rv ); + } + else + DOSMEM_GetBlock( bytes, &selector ); + + if (selector) + SET_AX( context, selector ); + else + { + SET_CFLAG(context); + SET_AX( context, 0x0008 ); /* insufficient memory */ + SET_BX( context, DOSMEM_Available() >> 4 ); + } + } + break; + case 0x49: /* FREE MEMORY */ + TRACE( "FREE MEMORY segment %04lX\n", context->SegEs ); + { + BOOL ok; + + if (!ISV86(context) && DOSVM_IsWin16()) + { + ok = !GlobalDOSFree16( context->SegEs ); + + /* If we don't reset ES_reg, we will fail in the relay code */ + if (ok) + context->SegEs = 0; + } + else + ok = DOSMEM_FreeBlock( (void*)((DWORD)context->SegEs << 4) ); + + if (!ok) + { + TRACE("FREE MEMORY failed\n"); + SET_CFLAG(context); + SET_AX( context, 0x0009 ); /* memory block address invalid */ + } + } + break; + case 0x4a: /* RESIZE MEMORY BLOCK */ INT_Int21Handler( context ); break; @@ -573,29 +664,21 @@ break; case 0x51: /* GET PSP ADDRESS */ - if (DOSVM_IsWin16()) { - INT_Int21Handler( context ); - break; - } - - TRACE("GET CURRENT PROCESS ID (GET PSP ADDRESS)\n"); - /* FIXME: should we return the original DOS PSP upon */ - /* Windows startup ? */ - SET_BX( context, DOSVM_psp ); + INT21_GetPSP( context ); break; case 0x52: /* "SYSVARS" - GET LIST OF LISTS */ - TRACE("SYSVARS - GET LIST OF LISTS\n"); - if (DOSVM_IsWin16()) + if (!ISV86(context) && DOSVM_IsWin16()) { - FIXME("LOLSeg broken for now\n"); - context->SegEs = 0; - SET_BX( context, 0 ); + SEGPTR ptr = DOSMEM_LOL()->wine_pm_lol; + context->SegEs = SELECTOROF(ptr); + SET_BX( context, OFFSETOF(ptr) ); } else { - context->SegEs = HIWORD(DOS_LOLSeg); - SET_BX( context, FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB) ); + SEGPTR ptr = DOSMEM_LOL()->wine_rm_lol; + context->SegEs = SELECTOROF(ptr); + SET_BX( context, OFFSETOF(ptr) ); } break; @@ -606,10 +689,29 @@ case 0x56: /* "RENAME" - RENAME FILE */ case 0x57: /* FILE DATE AND TIME */ - case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */ INT_Int21Handler( context ); break; + case 0x58: /* GET OR SET MEMORY ALLOCATION STRATEGY */ + TRACE( "GET OR SET MEMORY ALLOCATION STRATEGY, subfunction %d\n", + AL_reg(context) ); + switch (AL_reg(context)) + { + case 0x00: /* GET ALLOCATION STRATEGY */ + SET_AX( context, 1 ); /* low memory best fit */ + break; + + case 0x01: /* SET ALLOCATION STRATEGY */ + TRACE( "Set allocation strategy to %d - ignored\n", + BL_reg(context) ); + break; + + default: + INT_BARF( context, 0x21 ); + break; + } + break; + case 0x59: /* GET EXTENDED ERROR INFO */ INT21_GetExtendedError( context ); break; @@ -626,22 +728,29 @@ break; case 0x62: /* GET PSP ADDRESS */ - if (DOSVM_IsWin16()) { - INT_Int21Handler( context ); - break; - } - - TRACE("GET CURRENT PSP ADDRESS\n"); - /* FIXME: should we return the original DOS PSP upon */ - /* Windows startup ? */ - SET_BX( context, DOSVM_psp ); + INT21_GetPSP( context ); break; case 0x63: /* MISC. LANGUAGE SUPPORT */ + INT_Int21Handler( context ); + break; + case 0x64: /* OS/2 DOS BOX */ + INT_BARF( context, 0x21 ); + SET_CFLAG(context); + break; + case 0x65: /* GET EXTENDED COUNTRY INFORMATION */ case 0x66: /* GLOBAL CODE PAGE TABLE */ + INT_Int21Handler( context ); + break; + case 0x67: /* SET HANDLE COUNT */ + TRACE( "SET HANDLE COUNT to %d\n", BX_reg(context) ); + if (SetHandleCount( BX_reg(context) ) < BX_reg(context) ) + bSetDOSExtendedError = TRUE; + break; + case 0x68: /* "FFLUSH" - COMMIT FILE */ case 0x69: /* DISK SERIAL NUMBER */ case 0x6a: /* COMMIT FILE */ Index: dlls/winedos/dosexe.h =================================================================== RCS file: /home/wine/wine/dlls/winedos/dosexe.h,v retrieving revision 1.19 diff -u -r1.19 dosexe.h --- dlls/winedos/dosexe.h 2 Dec 2002 21:39:58 -0000 1.19 +++ dlls/winedos/dosexe.h 6 Dec 2002 21:54:04 -0000 @@ -57,7 +57,6 @@ extern WORD DOSVM_psp; /* psp of current DOS task */ extern WORD DOSVM_retval; /* return value of previous DOS task */ -extern DWORD DOS_LOLSeg; extern struct DPMI_segments *DOSVM_dpmi_segments; #if defined(linux) && defined(__i386__) && defined(HAVE_SYS_VM86_H) @@ -118,6 +117,9 @@ /* himem.c */ extern void DOSVM_InitSegments(void); +extern LPVOID DOSVM_AllocUMB(DWORD); +extern LPVOID DOSVM_AllocCodeUMB(DWORD, WORD *, WORD *); +extern LPVOID DOSVM_AllocDataUMB(DWORD, WORD *, WORD *); /* int09.c */ extern void WINAPI DOSVM_Int09Handler(CONTEXT86*); Index: dlls/winedos/himem.c =================================================================== RCS file: /home/wine/wine/dlls/winedos/himem.c,v retrieving revision 1.1 diff -u -r1.1 himem.c --- dlls/winedos/himem.c 2 Dec 2002 21:39:58 -0000 1.1 +++ dlls/winedos/himem.c 6 Dec 2002 21:54:42 -0000 @@ -66,7 +66,7 @@ * overhead. Use of this routine also preserves precious DOS * conventional memory. */ -static LPVOID DOSVM_AllocUMB( DWORD size ) +LPVOID DOSVM_AllocUMB( DWORD size ) { LPVOID ptr = (LPVOID)DOSVM_umb_free; @@ -89,7 +89,7 @@ * Initializes real mode segment and 16-bit protected mode selector * for the allocated code block. */ -static LPVOID DOSVM_AllocCodeUMB( DWORD size, WORD *segment, WORD *selector ) +LPVOID DOSVM_AllocCodeUMB( DWORD size, WORD *segment, WORD *selector ) { LPVOID ptr = DOSVM_AllocUMB( size ); @@ -98,6 +98,27 @@ if (selector) *selector = SELECTOR_AllocBlock( ptr, size, WINE_LDT_FLAGS_CODE ); + + return ptr; +} + + +/*********************************************************************** + * DOSVM_AllocDataUMB + * + * Allocate upper memory block for storing data. + * Initializes real mode segment and 16-bit protected mode selector + * for the allocated data block. + */ +LPVOID DOSVM_AllocDataUMB( DWORD size, WORD *segment, WORD *selector ) +{ + LPVOID ptr = DOSVM_AllocUMB( size ); + + if (segment) + *segment = (DWORD)ptr >> 4; + + if (selector) + *selector = SELECTOR_AllocBlock( ptr, size, WINE_LDT_FLAGS_DATA ); return ptr; } Index: dlls/winedos/devices.c =================================================================== RCS file: /home/wine/wine/dlls/winedos/devices.c,v retrieving revision 1.6 diff -u -r1.6 devices.c --- dlls/winedos/devices.c 31 Aug 2002 18:47:00 -0000 1.6 +++ dlls/winedos/devices.c 6 Dec 2002 21:54:48 -0000 @@ -456,13 +456,18 @@ void DOSDEV_InstallDOSDevices(void) { DOS_DATASEG *dataseg; - UINT16 seg; + WORD seg; + WORD selector; unsigned int n; /* allocate DOS data segment or something */ - DOS_LOLSeg = GlobalDOSAlloc16(sizeof(DOS_DATASEG)); - seg = HIWORD(DOS_LOLSeg); - dataseg = MapSL( MAKESEGPTR(LOWORD(DOS_LOLSeg), 0) ); + dataseg = DOSVM_AllocDataUMB( sizeof(DOS_DATASEG), &seg, &selector ); + + DOS_LOLSeg = MAKESEGPTR( seg, 0 ); + DOSMEM_LOL()->wine_rm_lol = + MAKESEGPTR( seg, FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB) ); + DOSMEM_LOL()->wine_pm_lol = + MAKESEGPTR( selector, FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB) ); /* initialize the magnificent List Of Lists */ InitListOfLists(&dataseg->lol); Index: dlls/winedos/module.c =================================================================== RCS file: /home/wine/wine/dlls/winedos/module.c,v retrieving revision 1.27 diff -u -r1.27 module.c --- dlls/winedos/module.c 28 Oct 2002 20:12:40 -0000 1.27 +++ dlls/winedos/module.c 6 Dec 2002 21:54:54 -0000 @@ -174,7 +174,7 @@ static void MZ_InitHandlers(void) { WORD seg; - LPBYTE start=DOSMEM_GetBlock(sizeof(int08),&seg); + LPBYTE start = DOSVM_AllocCodeUMB( sizeof(int08), &seg, 0 ); memcpy(start,int08,sizeof(int08)); /* INT 08: point it at our tick-incrementing handler */ ((SEGPTR*)0)[0x08]=MAKESEGPTR(seg,0); Index: msdos/int21.c =================================================================== RCS file: /home/wine/wine/msdos/int21.c,v retrieving revision 1.80 diff -u -r1.80 int21.c --- msdos/int21.c 3 Dec 2002 23:21:20 -0000 1.80 +++ msdos/int21.c 6 Dec 2002 21:55:00 -0000 @@ -468,22 +468,6 @@ SET_SI( context, context->Esi + (int)s - (int)filename ); } -static void INT21_GetSystemDate( CONTEXT86 *context ) -{ - SYSTEMTIME systime; - GetLocalTime( &systime ); - SET_CX( context, systime.wYear ); - SET_DX( context, (systime.wMonth << 8) | systime.wDay ); - SET_AX( context, systime.wDayOfWeek ); -} - -static void INT21_GetSystemTime( CONTEXT86 *context ) -{ - SYSTEMTIME systime; - GetLocalTime( &systime ); - SET_CX( context, (systime.wHour << 8) | systime.wMinute ); - SET_DX( context, (systime.wSecond << 8) | (systime.wMilliseconds / 10) ); -} /* Many calls translate a drive argument like this: drive number (00h = default, 01h = A:, etc) @@ -1106,14 +1090,6 @@ INT21_ParseFileNameIntoFCB(context); break; - case 0x2a: /* GET SYSTEM DATE */ - INT21_GetSystemDate(context); - break; - - case 0x2c: /* GET SYSTEM TIME */ - INT21_GetSystemTime(context); - break; - case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */ TRACE("GET DISK TRANSFER AREA ADDRESS\n"); { @@ -1510,52 +1486,6 @@ bSetDOSExtendedError = !INT21_GetCurrentDirectory(context); break; - case 0x48: /* ALLOCATE MEMORY */ - TRACE("ALLOCATE MEMORY for %d paragraphs\n", BX_reg(context)); - { - LPVOID *mem; - if (ISV86(context)) - { - mem= DOSMEM_GetBlock((DWORD)BX_reg(context)<<4,NULL); - if (mem) - SET_AX( context, DOSMEM_MapLinearToDos(mem)>>4 ); - } - else - { - mem = (LPVOID)GlobalDOSAlloc16(BX_reg(context)<<4); - if (mem) - SET_AX( context, (DWORD)mem&0xffff ); - } - if (!mem) - { - SET_CFLAG(context); - SET_AX( context, 0x0008 ); /* insufficient memory */ - SET_BX( context, DOSMEM_Available()>>4 ); - } - } - break; - - case 0x49: /* FREE MEMORY */ - TRACE("FREE MEMORY segment %04lX\n", context->SegEs); - { - BOOL ret; - if (ISV86(context)) - ret= DOSMEM_FreeBlock(DOSMEM_MapDosToLinear(context->SegEs<<4)); - else - { - ret = !GlobalDOSFree16(context->SegEs); - /* If we don't reset ES_reg, we will fail in the relay code */ - context->SegEs=ret; - } - if (!ret) - { - TRACE("FREE MEMORY failed\n"); - SET_CFLAG(context); - SET_AX( context, 0x0009 ); /* memory block address invalid */ - } - } - break; - case 0x4a: /* RESIZE MEMORY BLOCK */ TRACE("RESIZE MEMORY segment %04lX to %d paragraphs\n", context->SegEs, BX_reg(context)); if (!ISV86(context)) @@ -1596,17 +1526,6 @@ } else SET_AX( context, 0 ); /* OK */ break; - case 0x51: /* GET PSP ADDRESS */ - TRACE("GET CURRENT PROCESS ID (GET PSP ADDRESS)\n"); - /* FIXME: should we return the original DOS PSP upon */ - /* Windows startup ? */ - SET_BX( context, GetCurrentPDB16() ); - break; - case 0x62: /* GET PSP ADDRESS */ - /* FIXME: should we return the original DOS PSP upon */ - /* Windows startup ? */ - SET_BX( context, GetCurrentPDB16() ); - break; case 0x56: /* "RENAME" - RENAME FILE */ TRACE("RENAME %s to %s\n", @@ -1652,24 +1571,6 @@ } break; - case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */ - TRACE("GET OR SET MEMORY/UMB ALLOCATION STRATEGY subfunction %d\n", - AL_reg(context)); - switch (AL_reg(context)) - { - case 0x00: - SET_AX( context, 1 ); - break; - case 0x02: - SET_AX( context, 0 ); - break; - case 0x01: - case 0x03: - break; - } - RESET_CFLAG(context); - break; - case 0x5a: /* CREATE TEMPORARY FILE */ TRACE("CREATE TEMPORARY FILE\n"); bSetDOSExtendedError = !INT21_CreateTempFile(context); @@ -1746,10 +1647,6 @@ break; } break; - case 0x64: /* OS/2 DOS BOX */ - INT_BARF( context, 0x21 ); - SET_CFLAG(context); - break; case 0x65:{/* GET EXTENDED COUNTRY INFORMATION */ BYTE *dataptr=CTX_SEG_OFF_TO_LIN(context, context->SegEs,context->Edi); @@ -1810,12 +1707,6 @@ RESET_CFLAG(context); break; } - break; - - case 0x67: /* SET HANDLE COUNT */ - TRACE("SET HANDLE COUNT to %d\n",BX_reg(context) ); - SetHandleCount16( BX_reg(context) ); - if (GetLastError()) bSetDOSExtendedError = TRUE; break; case 0x68: /* "FFLUSH" - COMMIT FILE */ Index: dlls/kernel/kernel32.spec =================================================================== RCS file: /home/wine/wine/dlls/kernel/kernel32.spec,v retrieving revision 1.82 diff -u -r1.82 kernel32.spec --- dlls/kernel/kernel32.spec 2 Dec 2002 21:39:59 -0000 1.82 +++ dlls/kernel/kernel32.spec 6 Dec 2002 21:55:04 -0000 @@ -992,6 +992,7 @@ @ stdcall FindResource16(long str str) FindResource16 @ stdcall FreeResource16(long) FreeResource16 @ stdcall FreeSelector16(long) FreeSelector16 +@ stdcall GetCurrentPDB16() GetCurrentPDB16 @ stdcall GetCurrentTask() GetCurrentTask @ stdcall GetDOSEnvironment16() GetDOSEnvironment16 @ stdcall GetExePtr(long) GetExePtr -- Jukka Heinonen <http://www.iki.fi/jhei/>