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: 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);