Пример #1
0
bool DOS_ResizeMemory(Bit16u segment, Bit16u * blocks)
	{
	if (segment < DOS_MEM_START+1)
		E_Exit("Program tried to resize MCB block %X", segment);
	DOS_MCB mcb(segment-1);
	Bit8u mcb_type = mcb.GetType();
	if (mcb_type != 'M' && mcb_type != 'Z')
		{
		DOS_SetError(DOSERR_MCB_DESTROYED);
		return false;
		}

	Bit16u total = mcb.GetSize();
	if (*blocks == total)															// Same size, nothing to do
		return true;
	if (*blocks < total)															// Shrinking MCB
		{
		DOS_MCB	mcb_next(segment+(*blocks));
		mcb_next.SetType(mcb_type);
		mcb_next.SetSize(total-*blocks-1);
		mcb_next.SetPSPSeg(MCB_FREE);
		mcb.SetSize(*blocks);
		mcb.SetType('M');															// Further blocks follow
		DOS_CompressMemory();
		return true;
		}

	DOS_MCB	mcb_next(segment+total);												// MCB will grow, try to join with following MCB
	DOS_CompressMemory();
	if (mcb_type != 'Z' && mcb_next.GetPSPSeg() == MCB_FREE)
		{
		total += mcb_next.GetSize()+1;
		mcb_type = mcb_next.GetType();
		if (*blocks == total)
			{
			mcb.SetType(mcb_type);
			mcb.SetSize(*blocks);
			return true;
			}
		if (*blocks < total)
			{
			mcb_next.SetPt((Bit16u)(segment+*blocks));
			mcb_next.SetSize(total-*blocks-1);
			mcb_next.SetType(mcb_type);
			mcb_next.SetPSPSeg(MCB_FREE);
			mcb.SetSize(*blocks);
			mcb.SetType('M');
			return true;
			}
		}
	mcb.SetType(mcb_type);															// Not the required blocks available
	mcb.SetSize(total);
	*blocks = total;																// Return maximum
	DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
	return false;
	}
Пример #2
0
static void DOS_CompressMemory(void)
	{
	Bit16u mcb_segment = dos.firstMCB;
	DOS_MCB mcb(mcb_segment);
	DOS_MCB mcb_next(0);
	Bitu counter = 0;
	while (mcb.GetType() != 'Z')
		{
		if (counter++ > 1000)
			E_Exit("DOS MCB list corrupted.");
		mcb_next.SetPt((Bit16u)(mcb_segment+mcb.GetSize()+1));
		if ((mcb.GetPSPSeg() == MCB_FREE) && (mcb_next.GetPSPSeg() == MCB_FREE))
			{
			mcb.SetSize(mcb.GetSize()+mcb_next.GetSize()+1);
			mcb.SetType(mcb_next.GetType());
			}
		else
			{
			mcb_segment += mcb.GetSize()+1;
			mcb.SetPt(mcb_segment);
			if (mcb.GetType() == 'Z' && mcb_segment < EndConvMem && dos_infoblock.GetStartOfUMBChain() == EndConvMem)	// to UMB if used
				{
				mcb_segment = EndConvMem;
				mcb.SetPt(mcb_segment);
				}
			}
		}
	}
static void DOS_CompressMemory(void) {
	Bit16u mcb_segment=dos.firstMCB;
	DOS_MCB mcb(mcb_segment);
	DOS_MCB mcb_next(0);

	while (mcb.GetType()!=0x5a) {
		mcb_next.SetPt((Bit16u)(mcb_segment+mcb.GetSize()+1));
		if ((mcb.GetPSPSeg()==0) && (mcb_next.GetPSPSeg()==0)) {
			mcb.SetSize(mcb.GetSize()+mcb_next.GetSize()+1);
			mcb.SetType(mcb_next.GetType());
		} else {
			mcb_segment+=mcb.GetSize()+1;
			mcb.SetPt(mcb_segment);
		}
	}
}
Пример #4
0
static void DOS_CompressMemory(void) {
	Bit16u mcb_segment=dos.firstMCB;
	DOS_MCB mcb(mcb_segment);
	DOS_MCB mcb_next(0);

	while (mcb.GetType()!=0x5a) {
		mcb_next.SetPt((Bit16u)(mcb_segment+mcb.GetSize()+1));
		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 {
			mcb_segment+=mcb.GetSize()+1;
			mcb.SetPt(mcb_segment);
		}
	}
}
Пример #5
0
bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) {
	DOS_CompressMemory();
	Bit16u bigsize=0;
	Bit16u mem_strat=memAllocStrategy;
	Bit16u mcb_segment=dos.firstMCB;

	Bit16u umb_start=dos_infoblock.GetStartOfUMBChain();
	if (umb_start==UMB_START_SEG) {
		/* start with UMBs if requested (bits 7 or 6 set) */
		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);
	char psp_name[9];
	psp_mcb.GetFileName(psp_name);
	Bit16u found_seg=0,found_seg_size=0;
	for (;;) {
		mcb.SetPt(mcb_segment);
		if (mcb.GetPSPSeg()==MCB_FREE) {
			/* Check for enough free memory in current block */
			Bit16u block_size=mcb.GetSize();			
			if (block_size<(*blocks)) {
				if (bigsize<block_size) {
					/* current block is largest block that was found,
					   but still not as big as requested */
					bigsize=block_size;
				}
			} else if ((block_size==*blocks) && ((mem_strat & 0x3f)<2)) {
				/* MCB fits precisely, use it if search strategy is firstfit or bestfit */
				mcb.SetPSPSeg(dos.psp());
				*segment=mcb_segment+1;
				return true;
			} else {
				switch (mem_strat & 0x3f) {
					case 0: /* firstfit */
						mcb_next.SetPt((Bit16u)(mcb_segment+*blocks+1));
						mcb_next.SetPSPSeg(MCB_FREE);
						mcb_next.SetType(mcb.GetType());
						mcb_next.SetSize(block_size-*blocks-1);
						mcb.SetSize(*blocks);
						mcb.SetType(0x4d);		
						mcb.SetPSPSeg(dos.psp());
						mcb.SetFileName(psp_name);
						//TODO Filename
						*segment=mcb_segment+1;
						return true;
					case 1: /* bestfit */
						if ((found_seg_size==0) || (block_size<found_seg_size)) {
							/* first fitting MCB, or smaller than the last that was found */
							found_seg=mcb_segment;
							found_seg_size=block_size;
						}
						break;
					default: /* everything else is handled as lastfit by dos */
						/* MCB is large enough, note it down */
						found_seg=mcb_segment;
						found_seg_size=block_size;
						break;
				}
			}
		}
		/* Onward to the next MCB if there is one */
		if (mcb.GetType()==0x5a) {
			if ((mem_strat&0x80) && (umb_start==UMB_START_SEG)) {
				/* bit 7 set: try high memory first, then low */
				mcb_segment=dos.firstMCB;
				mem_strat&=(~0xc0);
			} else {
				/* finished searching all requested MCB chains */
				if (found_seg) {
					/* a matching MCB was found (cannot occur for firstfit) */
					if ((mem_strat & 0x3f)==0x01) {
						/* bestfit, allocate block at the beginning of the MCB */
						mcb.SetPt(found_seg);

						mcb_next.SetPt((Bit16u)(found_seg+*blocks+1));
						mcb_next.SetPSPSeg(MCB_FREE);
						mcb_next.SetType(mcb.GetType());
						mcb_next.SetSize(found_seg_size-*blocks-1);

						mcb.SetSize(*blocks);
						mcb.SetType(0x4d);		
						mcb.SetPSPSeg(dos.psp());
						mcb.SetFileName(psp_name);
						//TODO Filename
						*segment=found_seg+1;
					} else {
						/* lastfit, allocate block at the end of the MCB */
						mcb.SetPt(found_seg);
						if (found_seg_size==*blocks) {
							/* use the whole block */
							mcb.SetPSPSeg(dos.psp());
							//Not consistent with line 124. But how many application will use this information ?
							mcb.SetFileName(psp_name);
							*segment = found_seg+1;
							return true;
						}
						*segment = found_seg+1+found_seg_size - *blocks;
						mcb_next.SetPt((Bit16u)(*segment-1));
						mcb_next.SetSize(*blocks);
						mcb_next.SetType(mcb.GetType());
						mcb_next.SetPSPSeg(dos.psp());
						mcb_next.SetFileName(psp_name);
						// Old Block
						mcb.SetSize(found_seg_size-*blocks-1);
						mcb.SetPSPSeg(MCB_FREE);
						mcb.SetType(0x4D);
					}
					return true;
				}
				/* no fitting MCB found, return size of largest block */
				*blocks=bigsize;
				DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
				return false;
			}
		} else mcb_segment+=mcb.GetSize()+1;
	}
	return false;
}
Пример #6
0
bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) {
	if (segment < DOS_MEM_START+1) {
		LOG(LOG_DOSMISC,LOG_ERROR)("Program resizes %X, take care",segment);
	}
      
	DOS_MCB mcb(segment-1);
	if ((mcb.GetType()!=0x4d) && (mcb.GetType()!=0x5a)) {
		DOS_SetError(DOSERR_MCB_DESTROYED);
		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 */
			return true;
		}
		/* Shrinking MCB */
		DOS_MCB	mcb_new_next(segment+(*blocks));
		mcb.SetSize(*blocks);
		mcb_new_next.SetType(mcb.GetType());
		if (mcb.GetType()==0x5a) {
			/* Further blocks follow */
			mcb.SetType(0x4d);
		}

		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 */
	if (mcb.GetType()!=0x5a) {
		if (mcb_next.GetPSPSeg()==MCB_FREE) {
			total+=mcb_next.GetSize()+1;
		}
	}
	if (*blocks<total) {
		if (mcb.GetType()!=0x5a) {
			/* save type of following MCB */
			mcb.SetType(mcb_next.GetType());
		}
		mcb.SetSize(*blocks);
		mcb_next.SetPt((Bit16u)(segment+*blocks));
		mcb_next.SetSize(total-*blocks-1);
		mcb_next.SetType(mcb.GetType());
		mcb_next.SetPSPSeg(MCB_FREE);
		mcb.SetType(0x4d);
		mcb.SetPSPSeg(dos.psp());
		return true;
	}

	/* at this point: *blocks==total (fits) or *blocks>total,
	   in the second case resize block to maximum */

	if ((mcb_next.GetPSPSeg()==MCB_FREE) && (mcb.GetType()!=0x5a)) {
		/* adjust type of joined MCB */
		mcb.SetType(mcb_next.GetType());
	}
	mcb.SetSize(total);
	mcb.SetPSPSeg(dos.psp());
	if (*blocks==total) return true;	/* block fit exactly */

	*blocks=total;	/* return maximum */
	DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
	return false;
}
Пример #7
0
bool DOS_AllocateMemory(Bit16u * segment, Bit16u * reqBlocks)
	{
	DOS_CompressMemory();															// Mainly to check the NCB chain
	Bit16u bigsize = 0;
	Bit16u mem_strat = memAllocStrategy;
	Bit16u mcb_segment = dos.firstMCB;

	Bit16u umb_start = dos_infoblock.GetStartOfUMBChain();
	if (umb_start == EndConvMem && (mem_strat&0xc0))								// Start with UMBs if requested (bits 7 or 6 set)
		mcb_segment = umb_start;

	DOS_MCB mcb(0);
	DOS_MCB mcb_next(0);
	DOS_MCB psp_mcb(dos.psp()-1);
	char psp_name[9];
	psp_mcb.GetFileName(psp_name);
	Bit16u foundSeg = 0, foundSize = 0;
	for (;;)
		{
		mcb.SetPt(mcb_segment);
		if (mcb.GetPSPSeg() == MCB_FREE)
			{
			Bit16u block_size = mcb.GetSize();			
			if (block_size < (*reqBlocks))											// Check for enough free memory in current block
				{
				if (bigsize < block_size)											// Current block is largest block that was found, but still not as big as requested
					bigsize = block_size;
				}
			else if ((block_size == *reqBlocks) && ((mem_strat & 0x3f) < 2))		// MCB fits precisely, use it if search strategy is firstfit or bestfit
				{
				mcb.SetPSPSeg(dos.psp());
				mcb.SetFileName(psp_name);
				*segment = mcb_segment+1;
				return true;
				}
			else																	// Found block is larger than requested
				{
				switch (mem_strat & 0x3f)
					{
				case 0:																// Firstfit
					mcb_next.SetPt((Bit16u)(mcb_segment+*reqBlocks+1));
					mcb_next.SetPSPSeg(MCB_FREE);
					mcb_next.SetType(mcb.GetType());
					mcb_next.SetSize(block_size-*reqBlocks-1);
					mcb.SetSize(*reqBlocks);
					mcb.SetType('M');		
					mcb.SetPSPSeg(dos.psp());
					mcb.SetFileName(psp_name);
					*segment = mcb_segment+1;
					return true;
				case 1:																// Bestfit
					if ((foundSize == 0) || (block_size < foundSize))				// First fitting MCB, or smaller than the last that was found
						{
						foundSeg = mcb_segment;
						foundSize = block_size;
						}
					break;
				default:															// Everything else is handled as lastfit by DOS
					foundSeg = mcb_segment;											// MCB is large enough, note it down
					foundSize = block_size;
					break;
					}
				}
			}
		
		if (mcb.GetType() == 'Z')													// Onward to the next MCB if there is one
			{
			if ((mem_strat&0x80) && (umb_start == EndConvMem))
				{
				mcb_segment = dos.firstMCB;											// Bit 7 set: try upper memory first, then low
				mem_strat &= (~0xc0);
				}
			else																	// Finished searching all requested MCB chains
				{
				if (foundSeg)														// A matching MCB was found (cannot occur for firstfit)
					{
					if ((mem_strat & 0x3f) == 1)									// Bestfit, allocate block at the beginning of the MCB
						{
						mcb.SetPt(foundSeg);
						mcb_next.SetPt((Bit16u)(foundSeg+*reqBlocks+1));
						mcb_next.SetPSPSeg(MCB_FREE);
						mcb_next.SetType(mcb.GetType());
						mcb_next.SetSize(foundSize-*reqBlocks-1);
						mcb.SetSize(*reqBlocks);
						mcb.SetType('M');		
						mcb.SetPSPSeg(dos.psp());
						mcb.SetFileName(psp_name);
						*segment = foundSeg+1;
						}
					else															// Lastfit, allocate block at the end of the MCB
						{
						mcb.SetPt(foundSeg);
						if (foundSize == *reqBlocks)								// If requested size
							{
							mcb.SetPSPSeg(dos.psp());
							mcb.SetFileName(psp_name);
							*segment = foundSize+1;
							return true;
							}
						*segment = foundSeg+1+foundSize-*reqBlocks;
						mcb_next.SetPt((Bit16u)(*segment-1));
						mcb_next.SetSize(*reqBlocks);
						mcb_next.SetType(mcb.GetType());
						mcb_next.SetPSPSeg(dos.psp());
						mcb_next.SetFileName(psp_name);
						mcb.SetSize(foundSize-*reqBlocks-1);
						mcb.SetPSPSeg(MCB_FREE);
						mcb.SetType('M');
						}
					return true;
					}
				*reqBlocks = bigsize;												// No fitting MCB found, return size of largest block
				DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
				return false;
				}
			}
		else
			mcb_segment += mcb.GetSize()+1;
		}
	return false;
	}