Пример #1
0
static unsigned long depackedlen(const unsigned char *p, unsigned long plen) {
	if (p[0] == 'P' && p[1] == 'P' && p[2] == '2' && p[3] == '0')
		return val(p+plen-4);

	if (host_readd((Bit8u*)p) == plen)
		return val(p+plen-4);

	if (host_readd((Bit8u*)p) + 8 == plen)
		return val(p+plen-4);
	return 0; /* not a powerpacker file */
}
Пример #2
0
/**
 * menu_enter_delete() - selects a hero to enter / get deleted
 * @ptr:	pointer
 * @entries:	how many heros
 * @mode:	1 = enter / -1 = delete
 *
 * Returns: the number of the selected hero.
 * Used only in temples.
 */
signed short menu_enter_delete(RealPt ptr, signed short entries, signed short mode)
{
	signed short i;
	signed short answer;
	signed short a;
	signed short l_di;

	answer = 0;
	l_di = 0;

	while (answer != -1) {

		a = (l_di + 10 < entries) ? 10 : entries - l_di;

		/* fill a pointer array with the pointer to the names */
		for (i = 0; i < a; i++) {
			ds_writed(0xbf95 + 4 * i,
				(Bit32u)((i + l_di) * 32 + ptr + 0x10));
		}

		i = a;
		if (entries > 10) {
			ds_writed(0xbf95 + 4 * i,
				host_readd(Real2Host((RealPt)ds_readd(TEXT_LTX) + 0x48c)));
			i++;
		}

		answer = GUI_radio( (mode == -1) ? get_ltx(0x8dc) : get_ltx(0x490),
				(signed char)i,
				Real2Host(ds_readd(0xbf95)),
				Real2Host(ds_readd(0xbf99)),
				Real2Host(ds_readd(0xbf9d)),
				Real2Host(ds_readd(0xbfa1)),
				Real2Host(ds_readd(0xbfa5)),
				Real2Host(ds_readd(0xbfa9)),
				Real2Host(ds_readd(0xbfad)),
				Real2Host(ds_readd(0xbfb1)),
				Real2Host(ds_readd(0xbfb5)),
				Real2Host(ds_readd(0xbfb9)),
				Real2Host(ds_readd(0xbfbd)),
				Real2Host(ds_readd(0xbfc1)));

		if ((entries > 10) && (answer == i)) {
			l_di += 10;

			if (l_di > entries) {
				l_di = 0;
			}

		} else {

			if (answer != -1) {
				return l_di + answer - 1;
			}
		}
	}

	return -1;
}
Пример #3
0
static INLINE Bitu  hostRead(HostPt off ) {
	if ( sizeof( Size ) == 1)
		return host_readb( off );
	else if ( sizeof( Size ) == 2)
		return host_readw( off );
	else if ( sizeof( Size ) == 4)
		return host_readd( off );
	return 0;
}
Пример #4
0
void copy_3d_to_screen(void)
{
	Bit8u *src, *t_src;
	PhysPt dst, t_dst;
	signed short i, j;

	src = Real2Host(ds_readd(0xb128));
	dst = PhysMake(0xa000, 0x28f);

	i = 134;
	do {
		t_src = src;
		t_dst = dst;
		for (j = 52; j > 0; j--) {
			mem_writed_inline(t_dst, host_readd(t_src));
			t_dst+=4;
			t_src+=4;
		}
		src += 320;
		dst += 320;
		i--;
	} while (i != 0);
}
bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
	EXE_Header head;Bitu i;
	Bit16u fhandle;Bit16u len;Bit32u pos;
	Bit16u pspseg,envseg,loadseg,memsize,readsize;
	PhysPt loadaddress;RealPt relocpt;
	Bitu headersize,imagesize;
	DOS_ParamBlock block(block_pt);

	block.LoadData();
	if (flags!=LOADNGO && flags!=OVERLAY && flags!=LOAD) {
		E_Exit("DOS:Not supported execute mode %d for file %s",flags,name); 	
	}
	/* Check for EXE or COM File */
	bool iscom=false;
	if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false;
	len=sizeof(EXE_Header);
	if (!DOS_ReadFile(fhandle,(Bit8u *)&head,&len)) {
		DOS_CloseFile(fhandle);
		return false;
	}
	if (len<sizeof(EXE_Header)) {
		if (len==0) {
			/* Prevent executing zero byte files */
			DOS_SetError(DOSERR_ACCESS_DENIED);
			DOS_CloseFile(fhandle);
			return false;
		}
		/* Otherwise must be a .com file */
		iscom=true;
	} else {
		/* Convert the header to correct endian, i hope this works */
		HostPt endian=(HostPt)&head;
		for (i=0;i<sizeof(EXE_Header)/2;i++) {
			*((Bit16u *)endian)=host_readw(endian);
			endian+=2;
		}
		if ((head.signature!=MAGIC1) && (head.signature!=MAGIC2)) iscom=true;
		else {
			if(head.pages & ~0x07ff) /* 1 MB dos maximum address limit. Fixes TC3 IDE (kippesoep) */
				LOG(LOG_EXEC,LOG_NORMAL)("Weird header: head.pages > 1 MB");
			head.pages&=0x07ff;
			headersize = head.headersize*16;
			imagesize = head.pages*512-headersize; 
			if (imagesize+headersize<512) imagesize = 512-headersize;
		}
	}
	Bit8u * loadbuf=(Bit8u *)new Bit8u[0x10000];
	if (flags!=OVERLAY) {
		/* Create an environment block */
		envseg=block.exec.envseg;
		if (!MakeEnv(name,&envseg)) {
			DOS_CloseFile(fhandle);
			return false;
		}
		/* Get Memory */		
		Bit16u minsize,maxsize;Bit16u maxfree=0xffff;DOS_AllocateMemory(&pspseg,&maxfree);
		if (iscom) {
			minsize=0x1000;maxsize=0xffff;
			if (machine==MCH_PCJR) {
				/* try to load file into memory below 96k */ 
				pos=0;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET);	
				Bit16u dataread=0x1800;
				DOS_ReadFile(fhandle,loadbuf,&dataread);
				if (dataread<0x1800) maxsize=dataread;
				if (minsize>maxsize) minsize=maxsize;
			}
		} else {	/* Exe size calculated from header */
			minsize=long2para(imagesize+(head.minmemory<<4)+256);
			if (head.maxmemory!=0) maxsize=long2para(imagesize+(head.maxmemory<<4)+256);
			else maxsize=0xffff;
		}
		if (maxfree<minsize) {
			DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
			DOS_FreeMemory(envseg);
			return false;
		}
		if (maxfree<maxsize) memsize=maxfree;
		else memsize=maxsize;
		if (!DOS_AllocateMemory(&pspseg,&memsize)) E_Exit("DOS:Exec error in memory");
		if (iscom && (machine==MCH_PCJR) && (pspseg<0x2000)) {
			maxsize=0xffff;
			/* resize to full extent of memory block */
			DOS_ResizeMemory(pspseg,&maxsize);
			/* now try to lock out memory above segment 0x2000 */
			if ((real_readb(0x2000,0)==0x5a) && (real_readw(0x2000,1)==0) && (real_readw(0x2000,3)==0x7ffe)) {
				/* MCB after PCJr graphics memory region is still free */
				if (pspseg+maxsize==0x17ff) {
					DOS_MCB cmcb((Bit16u)(pspseg-1));
					cmcb.SetType(0x5a);		// last block
				}
			}
		}
		loadseg=pspseg+16;
		if (!iscom) {
			/* Check if requested to load program into upper part of allocated memory */
			if ((head.minmemory == 0) && (head.maxmemory == 0))
				loadseg = ((pspseg+memsize)*0x10-imagesize)/0x10;
		}
	} else loadseg=block.overlay.loadseg;
	/* Load the executable */
	loadaddress=PhysMake(loadseg,0);

	if (iscom) {	/* COM Load 64k - 256 bytes max */
		pos=0;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET);	
		readsize=0xffff-256;
		DOS_ReadFile(fhandle,loadbuf,&readsize);
		MEM_BlockWrite(loadaddress,loadbuf,readsize);
	} else {	/* EXE Load in 32kb blocks and then relocate */
		pos=headersize;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET);	
		while (imagesize>0x7FFF) {
			readsize=0x8000;DOS_ReadFile(fhandle,loadbuf,&readsize);
			MEM_BlockWrite(loadaddress,loadbuf,readsize);
//			if (readsize!=0x8000) LOG(LOG_EXEC,LOG_NORMAL)("Illegal header");
			loadaddress+=0x8000;imagesize-=0x8000;
		}
		if (imagesize>0) {
			readsize=(Bit16u)imagesize;DOS_ReadFile(fhandle,loadbuf,&readsize);
			MEM_BlockWrite(loadaddress,loadbuf,readsize);
//			if (readsize!=imagesize) LOG(LOG_EXEC,LOG_NORMAL)("Illegal header");
		}
		/* Relocate the exe image */
		Bit16u relocate;
		if (flags==OVERLAY) relocate=block.overlay.relocation;
		else relocate=loadseg;
		pos=head.reloctable;DOS_SeekFile(fhandle,&pos,0);
		for (i=0;i<head.relocations;i++) {
			readsize=4;DOS_ReadFile(fhandle,(Bit8u *)&relocpt,&readsize);
			relocpt=host_readd((HostPt)&relocpt);		//Endianize
			PhysPt address=PhysMake(RealSeg(relocpt)+loadseg,RealOff(relocpt));
			mem_writew(address,mem_readw(address)+relocate);
		}
	}
	delete[] loadbuf;
	DOS_CloseFile(fhandle);

	/* Setup a psp */
	if (flags!=OVERLAY) {
		// Create psp after closing exe, to avoid dead file handle of exe in copied psp
		SetupPSP(pspseg,memsize,envseg);
		SetupCMDLine(pspseg,block);
	};
	CALLBACK_SCF(false);		/* Carry flag cleared for caller if successfull */
	if (flags==OVERLAY) return true;			/* Everything done for overlays */
	RealPt csip,sssp;
	if (iscom) {
		csip=RealMake(pspseg,0x100);
		sssp=RealMake(pspseg,0xfffe);
		mem_writew(PhysMake(pspseg,0xfffe),0);
	} else {
		csip=RealMake(loadseg+head.initCS,head.initIP);
		sssp=RealMake(loadseg+head.initSS,head.initSP);
	}

	if (flags==LOAD) {
		DOS_PSP callpsp(dos.psp());
		/* Save the SS:SP on the PSP of calling program */
		callpsp.SetStack(RealMakeSeg(ss,reg_sp));
		/* Switch the psp's */
		dos.psp(pspseg);
		DOS_PSP newpsp(dos.psp());
		dos.dta(RealMake(newpsp.GetSegment(),0x80));
		block.exec.initsssp = sssp;
		block.exec.initcsip = csip;
		block.SaveData();
		return true;
	}

	if (flags==LOADNGO) {
		/* Get Caller's program CS:IP of the stack and set termination address to that */
		RealSetVec(0x22,RealMake(mem_readw(SegPhys(ss)+reg_sp+2),mem_readw(SegPhys(ss)+reg_sp)));
		SaveRegisters();
		DOS_PSP callpsp(dos.psp());
		/* Save the SS:SP on the PSP of calling program */
		callpsp.SetStack(RealMakeSeg(ss,reg_sp));
		/* Switch the psp's and set new DTA */
		dos.psp(pspseg);
		DOS_PSP newpsp(dos.psp());
		dos.dta(RealMake(newpsp.GetSegment(),0x80));
		/* save vectors */
		newpsp.SaveVectors();
		/* copy fcbs */
		newpsp.SetFCB1(block.exec.fcb1);
		newpsp.SetFCB2(block.exec.fcb2);
		/* Set the stack for new program */
		SegSet16(ss,RealSeg(sssp));reg_sp=RealOff(sssp);
		/* Add some flags and CS:IP on the stack for the IRET */
		reg_sp-=6;
		mem_writew(SegPhys(ss)+reg_sp+0,RealOff(csip));
		mem_writew(SegPhys(ss)+reg_sp+2,RealSeg(csip));
		/* DOS starts programs with a RETF, so our IRET
		   should not modify critical flags (IOPL in v86 mode);
		   interrupt flag is set explicitly, test flags cleared */
		mem_writew(SegPhys(ss)+reg_sp+4,(reg_flags&(~FMASK_TEST))|FLAG_IF);
		/* Setup the rest of the registers */
		reg_ax=reg_bx=0;reg_cx=0xff;
		reg_dx=pspseg;
		reg_si=RealOff(csip);
		reg_di=RealOff(sssp);
		reg_bp=0x91c;	/* DOS internal stack begin relict */
		SegSet16(ds,pspseg);SegSet16(es,pspseg);
#if C_DEBUG		
		/* Started from debug.com, then set breakpoint at start */
		DEBUG_CheckExecuteBreakpoint(RealSeg(csip),RealOff(csip));
#endif
		/* Add the filename to PSP and environment MCB's */
		char stripname[8];Bitu index=0;
		while (char chr=*name++) {
			switch (chr) {
			case ':':case '\\':case '/':index=0;break;
			default:if (index<8) stripname[index++]=toupper(chr);
			}
		}
		index=0;
		while (index<8) {
			if (stripname[index]=='.') break;
			if (!stripname[index]) break;	
			index++;
		}
		memset(&stripname[index],0,8-index);
		DOS_MCB pspmcb(dos.psp()-1);
		pspmcb.SetFileName(stripname);
		DOS_UpdatePSPName();
		return true;
	}
	return false;
}
Пример #6
0
static INLINE Bit32u Fetchd() {
	Bit32u temp=host_readd(core.cseip);
	core.cseip+=4;
	return temp;
}
Пример #7
0
//Initializer - is startet if executed file is SCHICKM.EXE/BLADEM.EXE or GEN.EXE
//Returns true if the desired programm is started
bool init_schick(char *name, unsigned short reloc, unsigned short _cs, unsigned short ip)
{

	char borsig[] = "Borland C++ - Copyright 1991 Borland Intl.";
	char fname[81];
	int ver;

	schick_get_fname(fname, name);

	if (strcmp(fname, "schickm.exe")
			&& strcmp(fname, "bladem.exe")
			&& strcmp(fname, "gen.exe")) return false;

	/* Check CS:IP in the EXE-Header are 0:0
	 * and the first executed instruction is mov dx,i16 */
	if (_cs != 0 || ip != 0 || real_readb(reloc+_cs, ip) != 0xba)
		return false;

	/* Show CS:IP on the virtual machine and the pointer to 0:0 */
	D1_TRAC("\n\nCS:IP 0x%x:0x%x\tMemBase: %p\n", reloc, ip, MemBase);

	/* Read and show the Datasegment */
	datseg_bak = datseg;
	datseg = real_readw(reloc, ip+1);
	p_datseg_bak = p_datseg;
	p_datseg = MemBase + PhysMake(datseg, 0);
	D1_TRAC("Dseg: 0x%X\n", datseg);

	/* Check if the start of the Datasegment is Borland C++ */
	if (host_readd(p_datseg) != 0 ||
		strcmp((char*)MemBase+PhysMake(datseg, 4), borsig)) {

		D1_ERR("Kein Borland C++ Kompilat!\n");
		return false;
	}

	/* check for the game program */
	if (!strcmp(fname, "schickm.exe") || !strcmp(fname, "bladem.exe")) {

		reloc_game = reloc;

		ver = schick_get_version((char*)p_datseg);

		if (ver == 0) {
			D1_ERR("Unbekannte Version von DSA1\n");
			return false;
		}

		D1_INFO("\nDSA1 Schicksalsklinge gefunden V%d.%02d_%s\n",
			ver / 100, ver % 100, schick_is_en() ? "en": "de");

		/* enable profiler only on this version */
		if (ver == 302 && !schick_is_en()) {
			D1_INFO("Starte Profiler\n");

			/* enable status comperator */
			schick_status_init();

			schick_timer_enable();

			schick++;
		}
	}

	/* check for the character generation program */
	if (!strcmp(fname, "gen.exe")) {
		reloc_gen = reloc;
		ver = schick_gen_get_version((char*)p_datseg);

		if (ver == 0) {
			D1_ERR("Unbekannte Version von DSA1 Generierung\n");
			return false;
		}

		D1_INFO("DSA1 Generierung gefunden V%d.%02d_%s\n",
			ver / 100, ver % 100, schick_gen_is_en() ? "en": "de");

		/* This happens only gen is started from the game.
		   We have to save some values. */

		if (!fromgame && schick && !gen) {
			if (schick_get_version((char*)p_datseg_bak) == 302 && !schick_is_en()) {
				schick_status_disable();
				schick_timer_disable();
		}
			schick--;
			fromgame++;

			D1_INFO("Gen gestartet\nreloc (0x%x)\n",
				(unsigned int)reloc_gen);
		}

		/* enable profiler only on this version */
		if (ver == 105 && !schick_is_en()) {
			D1_INFO("Starte Profiler\n");
			gen++;
		}
	}

	return true;
}