From 5fef7164a5edf42cf2d74089212be5316c937541 Mon Sep 17 00:00:00 2001 From: ripsaw8080 Date: Tue, 6 Jan 2015 17:48:07 +0000 Subject: [PATCH] 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 --- src/dos/dos_memory.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/dos/dos_memory.cpp b/src/dos/dos_memory.cpp index 7a86a0ea..7ab32bdb 100644 --- a/src/dos/dos_memory.cpp +++ b/src/dos/dos_memory.cpp @@ -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 */