Beispiel #1
0
void DOS_FreeProcessMemory(Bit16u pspseg) {
	Bit16u mcb_segment=dos.firstMCB;
	DOS_MCB mcb(mcb_segment);
	for (;;) {
		if (mcb.GetPSPSeg()==pspseg) {
			mcb.SetPSPSeg(MCB_FREE);
		}
		if (mcb.GetType()==0x5a) {
			/* check if currently last block reaches up to the PCJr graphics memory */
			if ((machine==MCH_PCJR) && (mcb_segment+mcb.GetSize()==0x17fe) &&
			   (real_readb(0x17ff,0)==0x4d) && (real_readw(0x17ff,1)==8)) {
				/* re-enable the memory past segment 0x2000 */
				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);
	}

	Bit16u umb_start=dos_infoblock.GetStartOfUMBChain();
	if (umb_start==UMB_START_SEG) {
		DOS_MCB umb_mcb(umb_start);
		for (;;) {
			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();
}
Beispiel #2
0
void UnMount(int i_drive) {
	if (dos_kernel_disabled)
		return;

	i_drive = toupper(i_drive);
	if(i_drive-'A' == DOS_GetDefaultDrive()) {
		DOS_MCB mcb(dos.psp()-1);
		static char name[9];
		mcb.GetFileName(name);
		if (!strlen(name)) goto umount;
		LOG_MSG("GUI:Drive %c is being used. Aborted.",i_drive);
		return;
	};
umount:
	if (i_drive-'A' < DOS_DRIVES && i_drive-'A' >= 0 && Drives[i_drive-'A']) {
		switch (DriveManager::UnmountDrive(i_drive-'A')) {
		case 0:
			Drives[i_drive-'A'] = 0;
			if(i_drive-'A' == DOS_GetDefaultDrive()) 
				DOS_SetDrive(toupper('Z') - 'A');
			LOG_MSG("GUI:Drive %c has succesfully been removed.",i_drive); break;
		case 1:
			LOG_MSG("GUI:Virtual Drives can not be unMOUNTed."); break;
		case 2:
			LOG_MSG(MSCDEX_Output(1).c_str()); break;
		}
	}
}
void DOS_BuildUMBChain()
	{
	Bit16u first_umb_seg = DOS_PRIVATE_SEGMENT_END;
	Bit16u first_umb_size = 0xf000 - first_umb_seg - (TotEMSMB ? 0x1000 : 0);

	dos_infoblock.SetStartOfUMBChain(EndConvMem);
	dos_infoblock.SetUMBChainState(0);										// UMBs not linked yet

	DOS_MCB umb_mcb(first_umb_seg);
	umb_mcb.SetPSPSeg(MCB_FREE);											// Currently free
	umb_mcb.SetSize(first_umb_size-1);
	umb_mcb.SetType('Z');

	Bit16u mcb_segment = dos.firstMCB;										// Scan MCB-chain for last block
	DOS_MCB mcb(mcb_segment);
	while (mcb.GetType() != 'Z')
		{
		mcb_segment += mcb.GetSize()+1;
		mcb.SetPt(mcb_segment);
		}
	Bit16u cover_mcb = (Bit16u)(mcb_segment+mcb.GetSize()+1);				// A system MCB has to cover the space between the regular MCB-chain and the UMBs
	mcb.SetPt(cover_mcb);
	mcb.SetType('M');
	mcb.SetPSPSeg(0x0008);
	mcb.SetSize(first_umb_seg-cover_mcb-1);
	mcb.SetFileName("SC      ");
	}
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);
				}
			}
		}
	}
bool DOS_GetFreeUMB(Bit16u * total, Bit16u * largest, Bit16u * count)
	{
	*total = *largest = *count = 0;
	Bit16u mcb_segment = dos_infoblock.GetStartOfUMBChain();
	if (mcb_segment != EndConvMem)
		return false;

	DOS_CompressMemory();
	DOS_MCB mcb(mcb_segment);
	while (1)
		{
		Bit16u mcb_size = mcb.GetSize();
		if (mcb.GetPSPSeg() == MCB_FREE)
			{
			*count += 1;
			*total += mcb_size;
			if (*largest < mcb_size)
				*largest = mcb_size;
			}
		if (mcb.GetType() == 'Z')
			break;
		mcb_segment += mcb_size+1;
		mcb.SetPt(mcb_segment);
		}
	return true;
	}
void DOS_UpdatePSPName(void) {
	DOS_MCB mcb(dos.psp()-1);
	static char name[9];
	mcb.GetFileName(name);
	if (!strlen(name)) strcpy(name,"DOSBOX");
	RunningProgram=name;
	GFX_SetTitle(-1,-1,false);
}
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;
	}
bool DOS_FreeMemory(Bit16u segment)
	{
// TODO Check if allowed to free this segment
	if (segment < DOS_MEM_START+1)
		E_Exit("Program tried to free MCB block %X", segment);
      
	DOS_MCB mcb(segment-1);
	if (mcb.GetType() != 'M' && mcb.GetType() != 'Z')
		{
		DOS_SetError(DOSERR_MB_ADDRESS_INVALID);
		return false;
		}
	mcb.SetPSPSeg(MCB_FREE);
//	DOS_CompressMemory();
	return true;
	}
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);
		}
	}
}
Beispiel #10
0
void SetVal(const std::string secname, std::string preval, const std::string val) {
	if(preval=="keyboardlayout" && !dos_kernel_disabled) {
		DOS_MCB mcb(dos.psp()-1);
		static char name[9];
		mcb.GetFileName(name);
		if (strlen(name)) {
			LOG_MSG("GUI: Exit %s running in DOSBox, and then try again.",name);
			return;
		}
	}
	Section* sec = control->GetSection(secname);
	if(sec) {
		std::string real_val=preval+"="+val;
		sec->HandleInputline(real_val);
	}
}
static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) {
	/* Fix the PSP for psp and environment MCB's */
	DOS_MCB mcb((Bit16u)(pspseg-1));
	mcb.SetPSPSeg(pspseg);
	mcb.SetPt((Bit16u)(envseg-1));
	mcb.SetPSPSeg(pspseg);

	DOS_PSP psp(pspseg);
	psp.MakeNew(memsize);
	psp.SetEnvironment(envseg);

	/* Copy file handles */
	DOS_PSP oldpsp(dos.psp());
	psp.CopyFileTable(&oldpsp,true);

}
Beispiel #12
0
bool DOS_FreeMemory(Bit16u segment) {
//TODO Check if allowed to free this segment
	if (segment < DOS_MEM_START+1) {
		LOG(LOG_DOSMISC,LOG_ERROR)("Program tried to free %X ---ERROR",segment);
		DOS_SetError(DOSERR_MB_ADDRESS_INVALID);
		return false;
	}
      
	DOS_MCB mcb(segment-1);
	if ((mcb.GetType()!=0x4d) && (mcb.GetType()!=0x5a)) {
		DOS_SetError(DOSERR_MB_ADDRESS_INVALID);
		return false;
	}
	mcb.SetPSPSeg(MCB_FREE);
//	DOS_CompressMemory();
	return true;
}
Beispiel #13
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);
		}
	}
}
void DOS_SetupMemory(bool low)
	{
	/* Let DOS claim a few bios interrupts. Makes vDos more compatible with 
	 * buggy games, which compare against the interrupt table. (probably a 
	 * broken linked list implementation) */
	Bitu cbID = CALLBACK_Allocate();												// DOS default int
	CALLBACK_Setup(cbID, &DOS_default_handler, CB_IRET, 0x708);
	RealSetVec(0x01, 0x700008);
	RealSetVec(0x03, 0x700008);
	RealSetVec(0x04, 0x700008);

	// Create a dummy device MCB with PSPSeg=0x0008
	DOS_MCB mcb_devicedummy((Bit16u)DOS_MEM_START);
	mcb_devicedummy.SetPSPSeg(MCB_DOS);				// Devices
	mcb_devicedummy.SetSize(1);
	mcb_devicedummy.SetType(0x4d);					// More blocks will follow
//	mcb_devicedummy.SetFileName("SD      ");

	Bit16u mcb_sizes = 2;
	// Create a small empty MCB (result from a growing environment block)
//	DOS_MCB tempmcb((Bit16u)DOS_MEM_START+mcb_sizes);
//	tempmcb.SetPSPSeg(MCB_FREE);
//	tempmcb.SetSize(4);
//	mcb_sizes += 5;
//	tempmcb.SetType(0x4d);

	int extra_size = low ? 0 : 4096 - DOS_MEM_START - mcb_sizes - 17;				// Disable first 64Kb if low not set in config
	// Lock the previous empty MCB
	DOS_MCB tempmcb2((Bit16u)DOS_MEM_START+mcb_sizes);
	tempmcb2.SetPSPSeg(0x40);
	tempmcb2.SetSize(16+extra_size);
	mcb_sizes += 17+extra_size;
	tempmcb2.SetType(0x4d);

	DOS_MCB mcb((Bit16u)DOS_MEM_START+mcb_sizes);
	mcb.SetPSPSeg(MCB_FREE);						// Free
	mcb.SetType(0x5a);								// Last Block
//	mcb.SetSize(0x9FFE - DOS_MEM_START - mcb_sizes);
	mcb.SetSize(EndConvMem - 1 - DOS_MEM_START - mcb_sizes);

	dos.firstMCB = DOS_MEM_START;
	dos_infoblock.SetFirstMCB(DOS_MEM_START);
	}
Beispiel #15
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 false;
	}

	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.firstMCB;
	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_FreeProcessMemory(Bit16u pspseg)
	{
	Bit16u mcb_segment = dos.firstMCB;
	DOS_MCB mcb(mcb_segment);

	for (int counter = 0; ; )
		{
		if (counter++ > 10000)
			E_Exit("DOS MCB list corrupted.");
		if (mcb.GetPSPSeg() == pspseg)
			mcb.SetPSPSeg(MCB_FREE);
		if (mcb.GetType() == 'Z')
			if (mcb_segment < EndConvMem && dos_infoblock.GetStartOfUMBChain() == EndConvMem)	// to UMB if used
				mcb_segment = EndConvMem;
			else
				break;
		else
			mcb_segment += mcb.GetSize()+1;
		mcb.SetPt(mcb_segment);
		}
	DOS_CompressMemory();
	}
bool DOS_LinkUMBsToMemChain(Bit16u linkstate)
	{
	Bit16u umb_start = dos_infoblock.GetStartOfUMBChain();					// Get start of UMB-chain
	if (umb_start != EndConvMem)
		return false;
	if ((linkstate&1) == (dos_infoblock.GetUMBChainState()&1))
		return true;
	
	Bit16u mcb_segment = dos.firstMCB;										// Scan MCB-chain for last block before UMB-chain
	Bit16u prev_mcb_segment = dos.firstMCB;
	DOS_MCB mcb(mcb_segment);
	while (mcb_segment != umb_start && mcb.GetType() != 'Z')
		{
		prev_mcb_segment = mcb_segment;
		mcb_segment += mcb.GetSize()+1;
		mcb.SetPt(mcb_segment);
		}
	DOS_MCB prev_mcb(prev_mcb_segment);

	switch (linkstate)
		{
	case 0:																	// Unlink
		if (prev_mcb.GetType() == 'M' && mcb_segment == umb_start)
			prev_mcb.SetType('Z');
		dos_infoblock.SetUMBChainState(0);
		break;
	case 1:																	// Link
		if (mcb.GetType() == 'Z')
			{
			mcb.SetType('M');
			dos_infoblock.SetUMBChainState(1);
			}
		break;
	default:
		return false;
		}
	return true;
	}
Beispiel #18
0
void DOS_BuildUMBChain(bool umb_active,bool ems_active) {
	if (umb_active  && (machine!=MCH_TANDY)) {
		Bit16u first_umb_seg = 0xd000;
		Bit16u first_umb_size = 0x2000;
		if(ems_active || (machine == MCH_PCJR)) first_umb_size = 0x1000;

		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      ");

	} else {
		dos_infoblock.SetStartOfUMBChain(0xffff);
		dos_infoblock.SetUMBChainState(0);
	}
}
Beispiel #19
0
void DOS_SetupMemory(void) {
	/* Let dos claim a few bios interrupts. Makes DOSBox more compatible with 
	 * buggy games, which compare against the interrupt table. (probably a 
	 * broken linked list implementation) */
	Bit16u ihseg = 0x70;
	Bit16u ihofs = 0x08;
	real_writeb(ihseg,ihofs,(Bit8u)0xCF);		//An IRET Instruction
	RealSetVec(0x01,RealMake(ihseg,ihofs));		//BioMenace (offset!=4)
	RealSetVec(0x02,RealMake(ihseg,ihofs));		//BioMenace (segment<0x8000)
	RealSetVec(0x03,RealMake(ihseg,ihofs));		//Alien Incident (offset!=0)
	RealSetVec(0x04,RealMake(ihseg,ihofs));		//Shadow President (lower byte of segment!=0)
	RealSetVec(0x0f,RealMake(ihseg,ihofs));		//Always a tricky one (soundblaster irq)

	// Create a dummy device MCB with PSPSeg=0x0008
	DOS_MCB mcb_devicedummy((Bit16u)DOS_MEM_START);
	mcb_devicedummy.SetPSPSeg(MCB_DOS);	// Devices
	mcb_devicedummy.SetSize(1);
	mcb_devicedummy.SetType(0x4d);		// More blocks will follow
//	mcb_devicedummy.SetFileName("SD      ");

	Bit16u mcb_sizes=2;
	// Create a small empty MCB (result from a growing environment block)
	DOS_MCB tempmcb((Bit16u)DOS_MEM_START+mcb_sizes);
	tempmcb.SetPSPSeg(MCB_FREE);
	tempmcb.SetSize(4);
	mcb_sizes+=5;
	tempmcb.SetType(0x4d);

	// Lock the previous empty MCB
	DOS_MCB tempmcb2((Bit16u)DOS_MEM_START+mcb_sizes);
	tempmcb2.SetPSPSeg(0x40);	// can be removed by loadfix
	tempmcb2.SetSize(16);
	mcb_sizes+=17;
	tempmcb2.SetType(0x4d);

	DOS_MCB mcb((Bit16u)DOS_MEM_START+mcb_sizes);
	mcb.SetPSPSeg(MCB_FREE);						//Free
	mcb.SetType(0x5a);								//Last Block
	if (machine==MCH_TANDY) {
		/* memory up to 608k available, the rest (to 640k) is used by
			the tandy graphics system's variable mapping of 0xb800 */
		mcb.SetSize(0x9BFF - DOS_MEM_START - mcb_sizes);
	} else if (machine==MCH_PCJR) {
		/* memory from 128k to 640k is available */
		mcb_devicedummy.SetPt((Bit16u)0x2000);
		mcb_devicedummy.SetPSPSeg(MCB_FREE);
		mcb_devicedummy.SetSize(0x9FFF - 0x2000);
		mcb_devicedummy.SetType(0x5a);

		/* exclude PCJr graphics region */
		mcb_devicedummy.SetPt((Bit16u)0x17ff);
		mcb_devicedummy.SetPSPSeg(MCB_DOS);
		mcb_devicedummy.SetSize(0x800);
		mcb_devicedummy.SetType(0x4d);

		/* memory below 96k */
		mcb.SetSize(0x1800 - DOS_MEM_START - (2+mcb_sizes));
		mcb.SetType(0x4d);
	} else {
		/* complete memory up to 640k available */
		/* last paragraph used to add UMB chain to low-memory MCB chain */
		mcb.SetSize(0x9FFE - DOS_MEM_START - mcb_sizes);
	}

	dos.firstMCB=DOS_MEM_START;
	dos_infoblock.SetFirstMCB(DOS_MEM_START);
}
Beispiel #20
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;
}
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;
	}
void DOS_SetupMemory(void) {
	/* Let dos claim a few bios interrupts. Makes DOSBox more compatible with 
	 * buggy games, which compare against the interrupt table. (probably a 
	 * broken linked list implementation) */
	callbackhandler.Allocate(&DOS_default_handler,"DOS default int");
	real_writeb(0x70,4,(Bit8u)0xFE);   //GRP 4
	real_writeb(0x70,5,(Bit8u)0x38);   //Extra Callback instruction
	real_writew(0x70,6,callbackhandler.Get_callback());  //The immediate word
	real_writeb(0x70,8,(Bit8u)0xCF);   //An IRET Instruction
	real_writed(0,0x01*4,0x700004);
	real_writed(0,0x02*4,0x700004); //BioMenace (segment<0x8000)
	real_writed(0,0x03*4,0x700004); //Alien Incident (offset!=0)
	real_writed(0,0x04*4,0x700004); //Shadow President (lower byte of segment!=0)
//	real_writed(0,0x0f*4,0x700004); //Always a tricky one (soundblaster irq)

	// Create a dummy device MCB with PSPSeg=0x0008
	DOS_MCB mcb_devicedummy((Bit16u)DOS_MEM_START);
	mcb_devicedummy.SetPSPSeg(MCB_DOS);	// Devices
	mcb_devicedummy.SetSize(1);
	mcb_devicedummy.SetType(0x4d);		// More blocks will follow
//	mcb_devicedummy.SetFileName("SD      ");

	Bit16u mcb_sizes=2;
	// Create a small empty MCB (result from a growing environment block)
	DOS_MCB tempmcb((Bit16u)DOS_MEM_START+mcb_sizes);
	tempmcb.SetPSPSeg(MCB_FREE);
	tempmcb.SetSize(4);
	mcb_sizes+=5;
	tempmcb.SetType(0x4d);

	// Lock the previous empty MCB
	DOS_MCB tempmcb2((Bit16u)DOS_MEM_START+mcb_sizes);
	tempmcb2.SetPSPSeg(0x40);	// can be removed by loadfix
	tempmcb2.SetSize(16);
	mcb_sizes+=17;
	tempmcb2.SetType(0x4d);

	DOS_MCB mcb((Bit16u)DOS_MEM_START+mcb_sizes);
	mcb.SetPSPSeg(MCB_FREE);						//Free
	mcb.SetType(0x5a);								//Last Block
	if (machine==MCH_TANDY) {
		/* memory up to 608k available, the rest (to 640k) is used by
			the tandy graphics system's variable mapping of 0xb800 */
		mcb.SetSize(0x97FE - DOS_MEM_START - mcb_sizes);
	} else if (machine==MCH_PCJR) {
		/* memory from 128k to 640k is available */
		mcb_devicedummy.SetPt((Bit16u)0x2000);
		mcb_devicedummy.SetPSPSeg(MCB_FREE);
		mcb_devicedummy.SetSize(0x9FFE - 0x2000);
		mcb_devicedummy.SetType(0x5a);

		/* exclude PCJr graphics region */
		mcb_devicedummy.SetPt((Bit16u)0x17ff);
		mcb_devicedummy.SetPSPSeg(MCB_DOS);
		mcb_devicedummy.SetSize(0x800);
		mcb_devicedummy.SetType(0x4d);

		/* memory below 96k */
		mcb.SetSize(0x1800 - DOS_MEM_START - (2+mcb_sizes));
		mcb.SetType(0x4d);
	} else {
		/* complete memory up to 640k available */
		mcb.SetSize(0x9FFE - DOS_MEM_START - mcb_sizes);
	}

	dos.firstMCB=DOS_MEM_START;
	dos_infoblock.SetFirstMCB(DOS_MEM_START);
}
void DOS_BuildUMBChain(const char* use_umbs,bool ems_active) {
	if ((strcmp(use_umbs,"false")!=0) && (machine!=MCH_TANDY)) {
		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) && (machine!=MCH_PCJR)) {
			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);
	}
}
Beispiel #24
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;
}
Beispiel #25
0
// change model callback
void MCSIEPlugin::setupProgramCtx(ProgramCtx& ctx)
{
  ProgramCtxData& pcd = ctx.getPluginData<MCSIE>();
  if( pcd.isEnabled() )
  {
    // setup predicate masks

    RegistryPtr reg(ctx.registry());

    // store registry in ProgramCtxData
    pcd.reg = reg;

    // configure predicate mask for d1/d2
    pcd.idd1 = reg->storeConstantTerm("d1");
    pcd.idd2 = reg->storeConstantTerm("d2");
    pcd.brdmask.setRegistry(reg);
    pcd.brdmask.addPredicate(pcd.idd1);
    pcd.brdmask.addPredicate(pcd.idd2);
    pcd.brd1mask.setRegistry(reg);
    pcd.brd1mask.addPredicate(pcd.idd1);
    pcd.brd2mask.setRegistry(reg);
    pcd.brd2mask.addPredicate(pcd.idd2);
    // configure collector (if we do not use them this will not hurt performance)
    pcd.mindcollector.reset(
        new MinimalNotionCollector(pcd.brd1mask, pcd.brd2mask));

    // configure predicate mask for e1/e2
    pcd.ide1 = reg->storeConstantTerm("e1");
    pcd.ide2 = reg->storeConstantTerm("e2");
    pcd.bremask.setRegistry(reg);
    pcd.bremask.addPredicate(pcd.ide1);
    pcd.bremask.addPredicate(pcd.ide2);
    pcd.bre1mask.setRegistry(reg);
    pcd.bre1mask.addPredicate(pcd.ide1);
    pcd.bre2mask.setRegistry(reg);
    pcd.bre2mask.addPredicate(pcd.ide2);
    // configure collector (if we do not use them this will not hurt performance)
    pcd.minecollector.reset(
        new MinimalNotionCollector(pcd.bre1mask, pcd.bre2mask));

    // configure predicate mask for each context's output beliefs
    assert(!pcd.mcs().contexts.empty() &&
           "here we expect to have parsed the input and "
           "we expect to know the number of contexts");
    for(ContextIterator it = pcd.mcs().contexts.begin();
        it != pcd.mcs().contexts.end(); ++it)
    {
      pcd.obmasks.push_back(PredicateMask());
      PredicateMask& mask = pcd.obmasks.back();

      std::ostringstream s;
      s << "a" << it->ContextNum();

      mask.setRegistry(reg);
      ID idob(reg->storeConstantTerm(s.str()));
      mask.addPredicate(idob);
    }

    // register model callbacks (accumulate minimal notions, print nonminimal notions)
    // register final callback (print minmimal notions, convert to dual notions)
    switch(pcd.getMode())
    {
    case ProgramCtxData::DIAGREWRITING:
      {
        PrintAndAccumulateModelCallback* ppcd =
            new PrintAndAccumulateModelCallback(pcd,
                pcd.idd1, pcd.idd2, pcd.brdmask, pcd.mindcollector);
        ModelCallbackPtr mcb(ppcd);
        WARNING("here we could try to only remove the default answer set printer")
        ctx.modelCallbacks.clear();
        ctx.modelCallbacks.push_back(mcb);
        FinalCallbackPtr fcb(new DiagRewritingFinalCallback(pcd, *ppcd, ctx.aspsoftware));
        ctx.finalCallbacks.push_back(fcb);
      }
      break;
    case ProgramCtxData::EXPLREWRITING:
      {
        PrintAndAccumulateModelCallback* ppcd =
            new PrintAndAccumulateModelCallback(pcd,
                pcd.ide1, pcd.ide2, pcd.bremask, pcd.minecollector);
        ModelCallbackPtr mcb(ppcd);
        WARNING("here we could try to only remove the default answer set printer")
        ctx.modelCallbacks.clear();
        ctx.modelCallbacks.push_back(mcb);
        FinalCallbackPtr fcb(new ExplRewritingFinalCallback(pcd, *ppcd, ctx.aspsoftware));
        ctx.finalCallbacks.push_back(fcb);
      }
      break;
    case ProgramCtxData::EQREWRITING:
      {
        ModelCallbackPtr mcb(new PrintEQModelCallback(pcd));
        WARNING("here we could try to only remove the default answer set printer")
        ctx.modelCallbacks.clear();
        ctx.modelCallbacks.push_back(mcb);
        // no final callback
      }
      break;
    }
  }
}