1
0
Fork 0

Coalesce free memory blocks after resizing a block rather than before. Fixes some MicroProse games on the Tandy machine type. Also add error exits in case of a corrupt MCB chain instead of hanging in an infinite loop.

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3882
This commit is contained in:
ripsaw8080 2015-01-06 17:48:07 +00:00
parent 58a149deec
commit 5fef7164a5

View file

@ -33,7 +33,8 @@ static void DOS_CompressMemory(void) {
while (mcb.GetType()!=0x5a) {
mcb_next.SetPt((Bit16u)(mcb_segment+mcb.GetSize()+1));
if ((mcb.GetPSPSeg()==0) && (mcb_next.GetPSPSeg()==0)) {
if (GCC_UNLIKELY((mcb_next.GetType()!=0x4d) && (mcb_next.GetType()!=0x5a))) E_Exit("Corrupt MCB chain");
if ((mcb.GetPSPSeg()==MCB_FREE) && (mcb_next.GetPSPSeg()==MCB_FREE)) {
mcb.SetSize(mcb.GetSize()+mcb_next.GetSize()+1);
mcb.SetType(mcb_next.GetType());
} else {
@ -58,6 +59,7 @@ void DOS_FreeProcessMemory(Bit16u pspseg) {
mcb.SetType(0x4d);
} else break;
}
if (GCC_UNLIKELY(mcb.GetType()!=0x4d)) E_Exit("Corrupt MCB chain");
mcb_segment+=mcb.GetSize()+1;
mcb.SetPt(mcb_segment);
}
@ -111,7 +113,7 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) {
Bit16u found_seg=0,found_seg_size=0;
for (;;) {
mcb.SetPt(mcb_segment);
if (mcb.GetPSPSeg()==0) {
if (mcb.GetPSPSeg()==MCB_FREE) {
/* Check for enough free memory in current block */
Bit16u block_size=mcb.GetSize();
if (block_size<(*blocks)) {
@ -225,12 +227,12 @@ bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) {
return false;
}
DOS_CompressMemory();
Bit16u total=mcb.GetSize();
DOS_MCB mcb_next(segment+total);
if (*blocks<=total) {
if (GCC_UNLIKELY(*blocks==total)) {
/* Nothing to do */
DOS_CompressMemory();
return true;
}
/* Shrinking MCB */
@ -245,6 +247,7 @@ bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) {
mcb_new_next.SetSize(total-*blocks-1);
mcb_new_next.SetPSPSeg(MCB_FREE);
mcb.SetPSPSeg(dos.psp());
DOS_CompressMemory();
return true;
}
/* MCB will grow, try to join with following MCB */
@ -265,6 +268,7 @@ bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) {
mcb_next.SetPSPSeg(MCB_FREE);
mcb.SetType(0x4d);
mcb.SetPSPSeg(dos.psp());
DOS_CompressMemory();
return true;
}
@ -277,6 +281,7 @@ bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) {
}
mcb.SetSize(total);
mcb.SetPSPSeg(dos.psp());
DOS_CompressMemory();
if (*blocks==total) return true; /* block fit exactly */
*blocks=total; /* return maximum */