adding support for upper memory
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2262
This commit is contained in:
parent
bc49a1ce91
commit
caff0f7a8b
9 changed files with 304 additions and 48 deletions
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue