Fix with how DOS_Execute allocates memory to comply with the memory allocation strategy for UMB...now, it will allocate and execute in UMB if there is enough memory for the minimum allocation of the executable

This commit is contained in:
Cimarron Mittelsteadt
2021-07-21 19:13:20 -07:00
parent 30f654c492
commit c3f5637e0e
3 changed files with 44 additions and 17 deletions

View File

@@ -233,6 +233,7 @@ void DOS_Terminate(uint16_t pspseg,bool tsr,uint8_t exitcode);
/* Memory Handling Routines */
void DOS_SetupMemory(void);
uint16_t DOS_GetMaximumFreeSize(uint16_t minBlocks);
bool DOS_AllocateMemory(uint16_t * segment,uint16_t * blocks);
bool DOS_ResizeMemory(uint16_t segment,uint16_t * blocks);
bool DOS_FreeMemory(uint16_t segment);
@@ -670,6 +671,11 @@ public:
uint8_t GetType(void) { return (uint8_t)sGet(sMCB,type);}
uint16_t GetSize(void) { return (uint16_t)sGet(sMCB,size);}
uint16_t GetPSPSeg(void) { return (uint16_t)sGet(sMCB,psp_segment);}
enum class MCBType : uint8_t
{
ValidBlock = 'M',
LastBlock = 'Z'
};
private:
#ifdef _MSC_VER
#pragma pack (1)

View File

@@ -366,6 +366,10 @@ bool DOS_Execute(const char* name, PhysPt block_pt, uint8_t flags) {
DOS_AllocateMemory(&pspseg,&maxfree);
if (iscom) {
minsize=0x1000;maxsize=0xffff;
pos=0;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET);
uint16_t dataread=0xf800;
DOS_ReadFile(fhandle,loadbuf,&dataread);
if (dataread<0xf800) minsize=((dataread+0x10)>>4)+0x20;
if (machine==MCH_PCJR) {
/* try to load file into memory below 96k */
pos=0;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET);
@@ -386,24 +390,15 @@ bool DOS_Execute(const char* name, PhysPt block_pt, uint8_t flags) {
* This allows it to run without the SS:IP out of range error below. */
if (maxsize < minsize) maxsize = minsize;
}
maxfree = DOS_GetMaximumFreeSize(minsize);
if (maxfree<minsize) {
if (iscom) {
/* Reduce minimum of needed memory size to filesize */
pos=0;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET);
uint16_t dataread=0xf800;
DOS_ReadFile(fhandle,loadbuf,&dataread);
if (dataread<0xf800) minsize=((dataread+0x10)>>4)+0x20;
}
if (maxfree<minsize) {
DOS_CloseFile(fhandle);
delete[] loadbuf;
DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
DOS_FreeMemory(envseg);
return false;
}
DOS_CloseFile(fhandle);
delete[] loadbuf;
DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
DOS_FreeMemory(envseg);
return false;
}
if (maxfree<maxsize) memsize=maxfree;
else memsize=maxsize;
memsize = (maxfree<maxsize) ? maxfree : maxsize;
if (!DOS_AllocateMemory(&pspseg,&memsize)) E_Exit("DOS:Exec error in memory");
if (iscom && (machine==MCH_PCJR) && (pspseg<0x2000)) {
maxsize=0xffff;

View File

@@ -16,8 +16,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <algorithm>
#include "dosbox.h"
#include "dosbox.h"
#include "logging.h"
#include "mem.h"
#include "bios.h"
@@ -153,6 +154,31 @@ void DOS_zeromem(uint16_t seg,uint16_t para) {
}
}
static uint16_t GetMaximumMCBFreeSize(uint16_t mcb_segment)
{
uint16_t largestSize = 0;
DOS_MCB mcb(mcb_segment);
for (bool endOfChain = false; !endOfChain; mcb.SetPt(mcb_segment))
{
auto size = mcb.GetSize();
if (mcb.GetPSPSeg()==MCB_FREE) largestSize = std::max(largestSize, size);
endOfChain = DOS_MCB::MCBType(mcb.GetType())==DOS_MCB::MCBType::LastBlock;
mcb_segment += size+1;
}
return largestSize;
}
uint16_t DOS_GetMaximumFreeSize(uint16_t minBlocks)
{
uint16_t umbFreeSize = 0;
if (memAllocStrategy & 0xc0)
{
umbFreeSize = GetMaximumMCBFreeSize(dos_infoblock.GetStartOfUMBChain());
if (memAllocStrategy & 0x40 || umbFreeSize >= minBlocks) return umbFreeSize;
}
return GetMaximumMCBFreeSize(dos.firstMCB);
}
bool DOS_AllocateMemory(uint16_t * segment,uint16_t * blocks) {
DOS_CompressMemory();
uint16_t bigsize=0;