1
0
Fork 0

adding support for upper memory

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2262
This commit is contained in:
Sebastian Strohhäcker 2005-08-08 13:33:46 +00:00
parent bc49a1ce91
commit caff0f7a8b
9 changed files with 304 additions and 48 deletions

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: callback.h,v 1.13 2005-07-30 09:49:28 qbix79 Exp $ */
/* $Id: callback.h,v 1.14 2005-08-08 13:33:43 c2woody Exp $ */
#ifndef DOSBOX_CALLBACK_H
#define DOSBOX_CALLBACK_H
@ -30,7 +30,7 @@ extern CallBack_Handler CallBack_Handlers[];
enum { CB_RETF,CB_IRET,CB_IRET_STI };
#define CB_MAX 1024
#define CB_MAX 144
#define CB_SEG 0xC800
#define CB_BASE (CB_SEG << 4)

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos_inc.h,v 1.54 2005-08-01 09:30:44 c2woody Exp $ */
/* $Id: dos_inc.h,v 1.55 2005-08-08 13:33:43 c2woody Exp $ */
#ifndef DOSBOX_DOS_INC_H
#define DOSBOX_DOS_INC_H
@ -76,13 +76,13 @@ enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3};
#define DOS_DRIVES 26
#define DOS_DEVICES 10
#define DOS_INFOBLOCK_SEG 0x50
#define DOS_SDA_SEG 0x5a
#define DOS_INFOBLOCK_SEG 0x80
#define DOS_CDS_SEG 0x90
#define DOS_CONSTRING_SEG 0xa0
#define DOS_CONDRV_SEG 0xa4
#define DOS_SDA_SEG 0xb0
#define DOS_SDA_OFS 0
#define DOS_CONSTRING_SEG 0x5d
#define DOS_CONDRV_SEG 0x60
#define DOS_SFT_SEG 0x62
#define DOS_CDS_SEG 0x64
#define DOS_MEM_START 0x102 //First Segment that DOS can use
/* internal Dos Tables */
@ -158,6 +158,8 @@ void DOS_FreeProcessMemory(Bit16u pspseg);
Bit16u DOS_GetMemory(Bit16u pages);
void DOS_SetMemAllocStrategy(Bit16u strat);
Bit16u DOS_GetMemAllocStrategy(void);
void DOS_BuildUMBChain(const char* use_umbs,bool ems_active);
bool DOS_LinkUMBsToMemChain(Bit16u linkstate);
/* FCB stuff */
bool DOS_FCBOpen(Bit16u seg,Bit16u offset);
@ -354,18 +356,24 @@ public:
DOS_InfoBlock () {};
void SetLocation(Bit16u seg);
void SetFirstMCB(Bit16u _first_mcb);
void SetfirstFileTable(RealPt _first_table);
void SetBuffers(Bit16u x,Bit16u y);
void SetCurDirStruct(Bit32u _curdirstruct);
void SetFCBTable(Bit32u _fcbtable);
void SetDeviceChainStart(Bit32u _devchain);
void SetDiskBufferHeadPt(Bit32u _dbheadpt);
RealPt GetPointer (void);
void SetStartOfUMBChain(Bit16u _umbstartseg);
void SetUMBChainState(Bit8u _umbchaining);
Bit16u GetStartOfUMBChain(void);
Bit8u GetUMBChainState(void);
RealPt GetPointer(void);
#ifdef _MSC_VER
#pragma pack(1)
#endif
struct sDIB {
Bit8u unknown1[4];
Bit16u magicWord; // -0x22 needs to be 1
Bit8u unknown2[8];
Bit16u regCXfrom5e; // -0x18 CX from last int21/ah=5e
Bit16u countLRUcache; // -0x16 LRU counter for FCB caching
Bit16u countLRUopens; // -0x14 LRU counter for FCB openings
@ -406,7 +414,7 @@ public:
Bit16u lookaheadBufNumber; // 0x51 number of lookahead buffers
Bit8u bufferLocation; // 0x53 workspace buffer location
Bit32u workspaceBuffer; // 0x54 pointer to workspace buffer
Bit8u unknown2[11]; // 0x58
Bit8u unknown3[11]; // 0x58
Bit8u chainingUMB; // 0x63 bit0: UMB chain linked to MCB chain
Bit16u minMemForExec; // 0x64 minimum paragraphs needed for current program
Bit16u startOfUMBChain; // 0x66 segment of first UMB-MCB

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos.cpp,v 1.84 2005-04-29 13:32:31 qbix79 Exp $ */
/* $Id: dos.cpp,v 1.85 2005-08-08 13:33:44 c2woody Exp $ */
#include <stdlib.h>
#include <string.h>
@ -716,12 +716,15 @@ static Bitu DOS_21Handler(void) {
DOS_SetMemAllocStrategy(reg_bx);
break;
case 2: /* Get UMB Link Status */
reg_ax=1; // no UMB support
CALLBACK_SCF(true);
reg_al=dos_infoblock.GetUMBChainState()&1;
CALLBACK_SCF(false);
break;
case 3: /* Set UMB Link Status */
reg_ax=1; // failure, no support
CALLBACK_SCF(true);
if (DOS_LinkUMBsToMemChain(reg_bx)) CALLBACK_SCF(false);
else {
reg_ax=1;
CALLBACK_SCF(true);
}
break;
default:
LOG(LOG_DOSMISC,LOG_ERROR)("DOS:58:Not Supported Set//Get memory allocation call %X",reg_al);

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos_classes.cpp,v 1.44 2005-08-01 09:30:45 c2woody Exp $ */
/* $Id: dos_classes.cpp,v 1.45 2005-08-08 13:33:45 c2woody Exp $ */
#include <string.h>
#include <stdlib.h>
@ -63,6 +63,7 @@ void DOS_InfoBlock::SetLocation(Bit16u segment) {
pt=PhysMake(seg,0);
/* Clear the initial Block */
for(Bitu i=0;i<sizeof(sDIB);i++) mem_writeb(pt+i,0xff);
for(Bitu i=0;i<14;i++) mem_writeb(pt+i,0);
sSave(sDIB,regCXfrom5e,(Bit16u)0);
sSave(sDIB,countLRUcache,(Bit16u)0);
@ -73,7 +74,7 @@ void DOS_InfoBlock::SetLocation(Bit16u segment) {
sSave(sDIB,joindedDrives,(Bit8u)0);
sSave(sDIB,lastdrive,(Bit8u)0x01);//increase this if you add drives to cds-chain
sSave(sDIB,diskInfoBuffer,RealMake(segment,0x5f));
sSave(sDIB,diskInfoBuffer,RealMake(segment,offsetof(sDIB,diskBufferHeadPt)));
sSave(sDIB,setverPtr,(Bit32u)0);
sSave(sDIB,a20FixOfs,(Bit16u)0);
@ -83,9 +84,12 @@ void DOS_InfoBlock::SetLocation(Bit16u segment) {
sSave(sDIB,bootDrive,(Bit8u)0);
sSave(sDIB,useDwordMov,(Bit8u)1);
sSave(sDIB,extendedSize,(Bit16u)0x4000); // >16mb
sSave(sDIB,magicWord,(Bit16u)0x0001); // dos5+
sSave(sDIB,sharingCount,(Bit16u)0);
sSave(sDIB,sharingDelay,(Bit16u)0);
sSave(sDIB,ptrCONinput,(Bit16u)0); // no unread input available
sSave(sDIB,maxSectorLength,(Bit16u)0x200);
sSave(sDIB,dirtyDiskBuffers,(Bit16u)0);
sSave(sDIB,lookaheadBufPt,(Bit32u)0);
@ -109,16 +113,20 @@ void DOS_InfoBlock::SetLocation(Bit16u segment) {
sSave(sDIB,nulString[5],(Bit8u)0x20);
sSave(sDIB,nulString[6],(Bit8u)0x20);
sSave(sDIB,nulString[7],(Bit8u)0x20);
/* Create a fake SFT, so programs think there are 100 file handles */
Bit16u sftOffset=offsetof(sDIB,firstFileTable)+0xa2;
sSave(sDIB,firstFileTable,RealMake(segment,sftOffset));
real_writed(segment,sftOffset+0x00,RealMake(segment+0x11,0)); //Next File Table
real_writew(segment,sftOffset+0x04,100); //File Table supports 100 files
real_writed(segment+0x11,0x00,0xffffffff); //Last File Table
real_writew(segment+0x11,0x04,100); //File Table supports 100 files
}
void DOS_InfoBlock::SetFirstMCB(Bit16u _firstmcb) {
sSave(sDIB,firstMCB,_firstmcb); //c2woody
}
void DOS_InfoBlock::SetfirstFileTable(RealPt _first_table) {
sSave(sDIB,firstFileTable,_first_table);
}
void DOS_InfoBlock::SetBuffers(Bit16u x,Bit16u y) {
sSave(sDIB,buffers_x,x);
sSave(sDIB,buffers_y,y);
@ -140,6 +148,22 @@ void DOS_InfoBlock::SetDiskBufferHeadPt(Bit32u _dbheadpt) {
sSave(sDIB,diskBufferHeadPt,_dbheadpt);
}
Bit16u DOS_InfoBlock::GetStartOfUMBChain(void) {
return sGet(sDIB,startOfUMBChain);
}
void DOS_InfoBlock::SetStartOfUMBChain(Bit16u _umbstartseg) {
sSave(sDIB,startOfUMBChain,_umbstartseg);
}
Bit8u DOS_InfoBlock::GetUMBChainState(void) {
return sGet(sDIB,chainingUMB);
}
void DOS_InfoBlock::SetUMBChainState(Bit8u _umbchaining) {
sSave(sDIB,chainingUMB,_umbchaining);
}
RealPt DOS_InfoBlock::GetPointer(void) {
return RealMake(seg,offsetof(sDIB,firstDPB));
}

View file

@ -20,6 +20,8 @@
#include "mem.h"
#include "dos_inc.h"
#define UMB_START_SEG 0x9fff
static Bit16u memAllocStrategy = 0x00;
static void DOS_CompressMemory(void) {
@ -50,6 +52,20 @@ void DOS_FreeProcessMemory(Bit16u pspseg) {
mcb_segment+=mcb.GetSize()+1;
mcb.SetPt(mcb_segment);
}
Bit16u umb_start=dos_infoblock.GetStartOfUMBChain();
if (umb_start==UMB_START_SEG) {
DOS_MCB umb_mcb(umb_start);
while (true) {
if (umb_mcb.GetPSPSeg()==pspseg) {
umb_mcb.SetPSPSeg(MCB_FREE);
}
if (umb_mcb.GetType()!=0x4d) break;
umb_start+=umb_mcb.GetSize()+1;
umb_mcb.SetPt(umb_start);
}
} else if (umb_start!=0xffff) LOG(LOG_DOSMISC,LOG_ERROR)("Corrupt UMB chain: %x",umb_start);
DOS_CompressMemory();
};
@ -65,7 +81,15 @@ void DOS_SetMemAllocStrategy(Bit16u strat)
bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) {
DOS_CompressMemory();
Bit16u bigsize=0;Bit16u mcb_segment=dos.firstMCB;
Bit16u bigsize=0;
Bit16u mem_strat=memAllocStrategy;
Bit16u mcb_segment=dos.firstMCB;
Bit16u umb_start=dos_infoblock.GetStartOfUMBChain();
if (umb_start==UMB_START_SEG) {
if (mem_strat&0xc0) mcb_segment=umb_start;
} else if (umb_start!=0xffff) LOG(LOG_DOSMISC,LOG_ERROR)("Corrupt UMB chain: %x",umb_start);
DOS_MCB mcb(0);
DOS_MCB mcb_next(0);
DOS_MCB psp_mcb(dos.psp()-1);
@ -88,7 +112,7 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) {
} else {
// TODO: Strategy "1": Best matching block
/* If so allocate it */
if ((memAllocStrategy & 0x03)==0) {
if ((mem_strat & 0x03)==0) {
mcb_next.SetPt((Bit16u)(mcb_segment+*blocks+1));
mcb_next.SetPSPSeg(MCB_FREE);
mcb_next.SetType(mcb.GetType());
@ -119,11 +143,15 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) {
}
/* Onward to the next MCB if there is one */
if (mcb.GetType()==0x5a) {
*blocks=bigsize;
DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
return false;
}
mcb_segment+=mcb.GetSize()+1;
if ((mem_strat&0x80) && (umb_start==UMB_START_SEG)) {
mcb_segment=dos.firstMCB;
mem_strat&=(~0xc0);
} else {
*blocks=bigsize;
DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
return false;
}
} else mcb_segment+=mcb.GetSize()+1;
}
return false;
}
@ -210,6 +238,109 @@ bool DOS_FreeMemory(Bit16u segment) {
}
void DOS_BuildUMBChain(const char* use_umbs,bool ems_active) {
if (strcmp(use_umbs,"false")!=0) {
Bit16u first_umb_seg=0xca00;
Bit16u first_umb_size=0x600;
if (strcmp(use_umbs,"max")==0) {
first_umb_seg-=0x100;
first_umb_size+=0x100;
}
dos_infoblock.SetStartOfUMBChain(UMB_START_SEG);
dos_infoblock.SetUMBChainState(0); // UMBs not linked yet
DOS_MCB umb_mcb(first_umb_seg);
umb_mcb.SetPSPSeg(0); // currently free
umb_mcb.SetSize(first_umb_size-1);
umb_mcb.SetType(0x5a);
/* Scan MCB-chain for last block */
Bit16u mcb_segment=dos.firstMCB;
DOS_MCB mcb(mcb_segment);
while (mcb.GetType()!=0x5a) {
mcb_segment+=mcb.GetSize()+1;
mcb.SetPt(mcb_segment);
}
/* A system MCB has to cover the space between the
regular MCB-chain and the UMBs */
Bit16u cover_mcb=(Bit16u)(mcb_segment+mcb.GetSize()+1);
mcb.SetPt(cover_mcb);
mcb.SetType(0x4d);
mcb.SetPSPSeg(0x0008);
mcb.SetSize(first_umb_seg-cover_mcb-1);
mcb.SetFileName("SC ");
if (!ems_active && (strcmp(use_umbs,"max")==0)) {
Bit16u ems_umb_seg=0xe000;
Bit16u ems_umb_size=0x1000;
/* Continue UMB-chain */
umb_mcb.SetSize(first_umb_size-2);
umb_mcb.SetType(0x4d);
DOS_MCB umb2_mcb(ems_umb_seg);
umb2_mcb.SetPSPSeg(0); // currently free
umb2_mcb.SetSize(ems_umb_size-1);
umb2_mcb.SetType(0x5a);
/* A system MCB has to take out the space between the previous and this UMB */
cover_mcb=(Bit16u)(first_umb_seg+umb_mcb.GetSize()+1);
mcb.SetPt(cover_mcb);
mcb.SetType(0x4d);
mcb.SetPSPSeg(0x0008);
mcb.SetSize(ems_umb_seg-cover_mcb-1);
mcb.SetFileName("SC ");
}
} else {
dos_infoblock.SetStartOfUMBChain(0xffff);
dos_infoblock.SetUMBChainState(0);
}
}
bool DOS_LinkUMBsToMemChain(Bit16u linkstate) {
/* Get start of UMB-chain */
Bit16u umb_start=dos_infoblock.GetStartOfUMBChain();
if (umb_start!=UMB_START_SEG) {
if (umb_start!=0xffff) LOG(LOG_DOSMISC,LOG_ERROR)("Corrupt UMB chain: %x",umb_start);
return true;
}
if ((linkstate&1)==(dos_infoblock.GetUMBChainState()&1)) return true;
/* Scan MCB-chain for last block before UMB-chain */
Bit16u mcb_segment=dos.firstMCB;
Bit16u prev_mcb_segment;
DOS_MCB mcb(mcb_segment);
while ((mcb_segment!=umb_start) && (mcb.GetType()!=0x5a)) {
prev_mcb_segment=mcb_segment;
mcb_segment+=mcb.GetSize()+1;
mcb.SetPt(mcb_segment);
}
DOS_MCB prev_mcb(prev_mcb_segment);
switch (linkstate) {
case 0x0000: // unlink
if ((prev_mcb.GetType()==0x4d) && (mcb_segment==umb_start)) {
prev_mcb.SetType(0x5a);
}
dos_infoblock.SetUMBChainState(0);
break;
case 0x0001: // link
if (mcb.GetType()==0x5a) {
mcb.SetType(0x4d);
dos_infoblock.SetUMBChainState(1);
}
break;
default:
LOG_MSG("Invalid link state %x when reconfiguring MCB chain",linkstate);
return false;
}
return true;
}
void DOS_SetupMemory(void) {
@ -218,6 +349,7 @@ void DOS_SetupMemory(void) {
mcb_devicedummy.SetPSPSeg(0x0008); // Devices
mcb_devicedummy.SetSize(1);
mcb_devicedummy.SetType(0x4d); // More blocks will follow
// mcb_devicedummy.SetFileName("SD ");
// BioMenace (segment of int2<0x8000)
mem_writeb((DOS_MEM_START+1)<<4,0xcf);// iret

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos_programs.cpp,v 1.38 2005-07-20 11:35:53 qbix79 Exp $ */
/* $Id: dos_programs.cpp,v 1.39 2005-08-08 13:33:45 c2woody Exp $ */
#include <stdlib.h>
#include <string.h>
@ -207,9 +207,40 @@ public:
void Run(void) {
/* Show conventional Memory */
WriteOut("\n");
Bit16u umb_start=dos_infoblock.GetStartOfUMBChain();
Bit8u umb_flag=dos_infoblock.GetUMBChainState();
Bit8u old_memstrat=DOS_GetMemAllocStrategy()&0xff;
if (umb_start!=0xffff) {
if ((umb_flag&1)==1) DOS_LinkUMBsToMemChain(0);
DOS_SetMemAllocStrategy(0);
}
Bit16u seg,blocks;blocks=0xffff;
DOS_AllocateMemory(&seg,&blocks);
WriteOut(MSG_Get("PROGRAM_MEM_CONVEN"),blocks*16/1024);
if (umb_start!=0xffff) {
DOS_LinkUMBsToMemChain(1);
DOS_SetMemAllocStrategy(0x40); // search in UMBs only
Bit16u largest_block=0,total_blocks=0,block_count=0;
for (;; block_count++) {
blocks=0xffff;
DOS_AllocateMemory(&seg,&blocks);
if (blocks==0) break;
total_blocks+=blocks;
if (blocks>largest_block) largest_block=blocks;
DOS_AllocateMemory(&seg,&blocks);
}
Bit8u current_umb_flag=dos_infoblock.GetUMBChainState();
if ((current_umb_flag&1)!=(umb_flag&1)) DOS_LinkUMBsToMemChain(umb_flag);
DOS_SetMemAllocStrategy(old_memstrat); // restore strategy
if (block_count>0) WriteOut(MSG_Get("PROGRAM_MEM_UPPER"),total_blocks*16/1024,block_count,largest_block*16/1024);
}
/* Test for and show free XMS */
reg_ax=0x4300;CALLBACK_RunRealInt(0x2f);
if (reg_al==0x80) {
@ -695,6 +726,7 @@ void DOS_SetupPrograms(void) {
MSG_Add("PROGRAM_MEM_CONVEN","%10d Kb free conventional memory\n");
MSG_Add("PROGRAM_MEM_EXTEND","%10d Kb free extended memory\n");
MSG_Add("PROGRAM_MEM_EXPAND","%10d Kb free expanded memory\n");
MSG_Add("PROGRAM_MEM_UPPER","%10d Kb free upper memory in %d blocks (largest UMB %d Kb)\n");
MSG_Add("PROGRAM_LOADFIX_ALLOC","%d kb allocated.\n");
MSG_Add("PROGRAM_LOADFIX_DEALLOC","%d kb freed.\n");

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos_tables.cpp,v 1.19 2005-08-01 09:30:45 c2woody Exp $ */
/* $Id: dos_tables.cpp,v 1.20 2005-08-08 13:33:46 c2woody Exp $ */
#include "dosbox.h"
#include "mem.h"
@ -100,15 +100,6 @@ void DOS_SetupTables(void) {
real_writed(seg,0x0e,0x20202020); // driver name
dos_infoblock.SetDeviceChainStart(RealMake(seg,0));
/* Create a fake SFT, so programs think there are 100 file handles */
seg=DOS_SFT_SEG;
seg2=DOS_SFT_SEG+1;
real_writed(seg,0,seg2<<16); //Next File Table
real_writew(seg,4,100); //File Table supports 100 files
real_writed(seg2,0,0xffffffff); //Last File Table
real_writew(seg2,4,100); //File Table supports 100 files
dos_infoblock.SetfirstFileTable(RealMake(seg,0));
/* Create a fake Current Directory Structure */
seg=DOS_CDS_SEG;
real_writed(seg,0x00,0x005c3a43);

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dosbox.cpp,v 1.86 2005-07-30 14:41:31 qbix79 Exp $ */
/* $Id: dosbox.cpp,v 1.87 2005-08-08 13:33:46 c2woody Exp $ */
#include <stdlib.h>
#include <stdarg.h>
@ -379,9 +379,11 @@ void DOSBOX_Init(void) {
secprop->Add_bool("xms",true);
secprop->AddInitFunction(&EMS_Init,true);//done
secprop->Add_bool("ems",true);
secprop->Add_string("umb","true");
MSG_Add("DOS_CONFIGFILE_HELP",
"xms -- Enable XMS support.\n"
"ems -- Enable EMS support.\n"
"umb -- Enable UMB support (false,true,max).\n"
);
// Mscdex
secprop->AddInitFunction(&MSCDEX_Init);

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: xms.cpp,v 1.35 2005-03-25 11:59:24 qbix79 Exp $ */
/* $Id: xms.cpp,v 1.36 2005-08-08 13:33:46 c2woody Exp $ */
#include <stdlib.h>
#include <string.h>
@ -55,6 +55,7 @@
#define XMS_QUERY_ANY_FREE_MEMORY 0x88
#define XMS_ALLOCATE_ANY_MEMORY 0x89
#define XMS_FUNCTION_NOT_IMPLEMENTED 0x80
#define HIGH_MEMORY_NOT_EXIST 0x90
#define HIGH_MEMORY_IN_USE 0x91
#define HIGH_MEMORY_NOT_ALLOCATED 0x93
@ -63,6 +64,8 @@
#define XMS_INVALID_HANDLE 0xa2
#define XMS_BLOCK_NOT_LOCKED 0xaa
#define XMS_BLOCK_LOCKED 0xab
#define UMB_ONLY_SMALLER_BLOCK 0xb0
#define UMB_NO_BLOCKS_AVAILABLE 0xb1
struct XMS_Block {
Bitu size;
@ -102,6 +105,7 @@ Bitu XMS_GetEnabledA20(void)
};
static RealPt xms_callback;
static bool umb_available;
static XMS_Block xms_handles[XMS_HANDLES];
@ -322,13 +326,57 @@ Bitu XMS_Handler(void) {
reg_bl = XMS_ResizeMemory(reg_dx, reg_bx);
reg_ax = (reg_bl==0);
break;
case XMS_ALLOCATE_UMB: /* 10 */
reg_ax=0;
reg_bl=0xb1; //No UMB Available
reg_dx=0;
case XMS_ALLOCATE_UMB: { /* 10 */
if (!umb_available) {
reg_ax=0;
reg_bl=XMS_FUNCTION_NOT_IMPLEMENTED;
break;
}
Bit16u umb_start=dos_infoblock.GetStartOfUMBChain();
if (umb_start==0xffff) {
reg_ax=0;
reg_bl=UMB_NO_BLOCKS_AVAILABLE;
reg_dx=0; // no upper memory available
break;
}
/* Save status and linkage of upper UMB chain and link upper
memory to the regular MCB chain */
Bit8u umb_flag=dos_infoblock.GetUMBChainState();
if ((umb_flag&1)==0) DOS_LinkUMBsToMemChain(1);
Bit8u old_memstrat=DOS_GetMemAllocStrategy()&0xff;
DOS_SetMemAllocStrategy(0x40); // search in UMBs only
Bit16u size=reg_dx;Bit16u seg;
if (DOS_AllocateMemory(&seg,&size)) {
reg_ax=1;
reg_bx=seg;
} else {
reg_ax=0;
if (size==0) reg_bl=UMB_NO_BLOCKS_AVAILABLE;
else reg_bl=UMB_ONLY_SMALLER_BLOCK;
reg_dx=size; // size of largest available UMB
}
/* Restore status and linkage of upper UMB chain */
Bit8u current_umb_flag=dos_infoblock.GetUMBChainState();
if ((current_umb_flag&1)!=(umb_flag&1)) DOS_LinkUMBsToMemChain(umb_flag);
DOS_SetMemAllocStrategy(old_memstrat);
}
break;
case XMS_DEALLOCATE_UMB: /* 11 */
LOG(LOG_MISC,LOG_ERROR)("XMS:Unhandled call %2X",reg_ah);
if (!umb_available) {
reg_ax=0;
reg_bl=XMS_FUNCTION_NOT_IMPLEMENTED;
break;
}
if (dos_infoblock.GetStartOfUMBChain()!=0xffff) {
if (DOS_FreeMemory(reg_dx)) {
reg_ax=0x0001;
break;
}
}
reg_ax=0x0000;
reg_bl=UMB_NO_BLOCKS_AVAILABLE;
break;
case XMS_QUERY_ANY_FREE_MEMORY: /* 88 */
reg_bl = XMS_QueryFreeMemory(reg_ax,reg_dx);
@ -336,6 +384,10 @@ Bitu XMS_Handler(void) {
reg_edx &= 0xffff;
reg_ecx = (MEM_TotalPages()*MEM_PAGESIZE)-1; // highest known physical memory address
break;
default:
LOG(LOG_MISC,LOG_ERROR)("XMS: unknown function %02X",reg_ah);
reg_ax=0;
reg_bl=XMS_FUNCTION_NOT_IMPLEMENTED;
}
// LOG(LOG_MISC,LOG_ERROR)("XMS: CALL Result: %02X",reg_bl);
return CBRET_NONE;
@ -346,6 +398,7 @@ private:
public:
XMS(Section* configuration):Module_base(configuration){
Section_prop * section=static_cast<Section_prop *>(configuration);
umb_available=false;
if (!section->Get_bool("xms")) return;
Bitu i;
BIOS_ZeroExtendedSize(true);
@ -373,10 +426,21 @@ public:
}
/* Disable the 0 handle */
xms_handles[0].free = false;
/* Set up UMB chain */
umb_available=strcmp(section->Get_string("umb"),"false")!=0;
DOS_BuildUMBChain(section->Get_string("umb"),section->Get_bool("ems"));
}
~XMS(){
Section_prop * section = static_cast<Section_prop *>(m_configuration);
/* Remove upper memory information */
dos_infoblock.SetStartOfUMBChain(0xffff);
if (umb_available) {
dos_infoblock.SetUMBChainState(0);
umb_available=false;
}
if (!section->Get_bool("xms")) return;
/* Undo biosclearing */
BIOS_ZeroExtendedSize(false);