Example #1
0
void INT10_SetupVESA(void) {
	/* Put the mode list somewhere in memory */
	Bitu i;
	i=0;
	int10.rom.vesa_modes=RealMake(0xc000,int10.rom.used);
//TODO Maybe add normal vga modes too, but only seems to complicate things
	while (ModeList_VGA[i].mode!=0xffff) {
		bool canuse_mode=false;
		if (!svga.accepts_mode) canuse_mode=true;
		else {
			if (svga.accepts_mode(ModeList_VGA[i].mode)) canuse_mode=true;
		}
		if (ModeList_VGA[i].mode>=0x100 && canuse_mode) {
			if ((!int10.vesa_oldvbe) || (ModeList_VGA[i].mode<0x120)) {
				phys_writew(PhysMake(0xc000,int10.rom.used),ModeList_VGA[i].mode);
				int10.rom.used+=2;
			}
		}
		i++;
	}
	phys_writew(PhysMake(0xc000,int10.rom.used),0xffff);
	int10.rom.used+=2;
	int10.rom.oemstring=RealMake(0xc000,int10.rom.used);
	Bitu len=(Bitu)(strlen(string_oem)+1);
	for (i=0;i<len;i++) {
		phys_writeb(0xc0000+int10.rom.used++,string_oem[i]);
	}
	switch (svgaCard) {
	case SVGA_S3Trio:
		break;
	}
	callback.setwindow=CALLBACK_Allocate();
	callback.pmPalette=CALLBACK_Allocate();
	callback.pmStart=CALLBACK_Allocate();
	CALLBACK_Setup(callback.setwindow,VESA_SetWindow,CB_RETF, "VESA Real Set Window");
	/* Prepare the pmode interface */
	int10.rom.pmode_interface=RealMake(0xc000,int10.rom.used);
	int10.rom.used += 8;		//Skip the byte later used for offsets
	/* PM Set Window call */
	int10.rom.pmode_interface_window = int10.rom.used - RealOff( int10.rom.pmode_interface );
	phys_writew( Real2Phys(int10.rom.pmode_interface) + 0, int10.rom.pmode_interface_window );
	callback.pmWindow=CALLBACK_Allocate();
	int10.rom.used += (Bit16u)CALLBACK_Setup(callback.pmWindow, VESA_PMSetWindow, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Window");
	/* PM Set start call */
	int10.rom.pmode_interface_start = int10.rom.used - RealOff( int10.rom.pmode_interface );
	phys_writew( Real2Phys(int10.rom.pmode_interface) + 2, int10.rom.pmode_interface_start);
	callback.pmStart=CALLBACK_Allocate();
	int10.rom.used += (Bit16u)CALLBACK_Setup(callback.pmStart, VESA_PMSetStart, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Start");
	/* PM Set Palette call */
	int10.rom.pmode_interface_palette = int10.rom.used - RealOff( int10.rom.pmode_interface );
	phys_writew( Real2Phys(int10.rom.pmode_interface) + 4, int10.rom.pmode_interface_palette);
	callback.pmPalette=CALLBACK_Allocate();
	int10.rom.used += (Bit16u)CALLBACK_Setup(callback.pmPalette, VESA_PMSetPalette, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Palette");
	/* Finalize the size and clear the required ports pointer */
	phys_writew( Real2Phys(int10.rom.pmode_interface) + 6, 0);
	int10.rom.pmode_interface_size=int10.rom.used - RealOff( int10.rom.pmode_interface );
}
void fill_smth(void)
{
	Bit8u *dst;
	Bit32u i;

	dst = MemBase + PhysMake(datseg, 0x78da);
	for (i = 104; i > 0; i--, dst += 4)
		host_writed(dst, 0x7fff7fff);
	dst = MemBase + PhysMake(datseg, 0x7a7a);
	for (i = 104; i > 0; i--, dst += 4)
		host_writed(dst, 0x80018001);
}
Example #3
0
Program::Program() {
	/* Find the command line and setup the PSP */
	psp = new DOS_PSP(dos.psp());
	/* Scan environment for filename */
	PhysPt envscan=PhysMake(psp->GetEnvironment(),0);
	while (mem_readb(envscan)) envscan+=mem_strlen(envscan)+1;	
	envscan+=3;
	CommandTail tail;
	MEM_BlockRead(PhysMake(dos.psp(),128),&tail,128);
	if (tail.count<127) tail.buffer[tail.count]=0;
	else tail.buffer[126]=0;
	char filename[256+1];
	MEM_StrCopy(envscan,filename,256);
	cmd = new CommandLine(filename,tail.buffer);
}
Example #4
0
Bit8u VESA_GetSVGAInformation(Bit16u seg,Bit16u off) {
	/* Fill 256 byte buffer with VESA information */
	PhysPt buffer=PhysMake(seg,off);
	Bitu i;
	bool vbe2=false;Bit16u vbe2_pos=256+off;
	Bitu id=mem_readd(buffer);
	if (((id==0x56424532)||(id==0x32454256)) && (!int10.vesa_oldvbe)) vbe2=true;
	if (vbe2) {
		for (i=0;i<0x200;i++) mem_writeb(buffer+i,0);		
	} else {
		for (i=0;i<0x100;i++) mem_writeb(buffer+i,0);
	}
	/* Fill common data */
	MEM_BlockWrite(buffer,(void *)"VESA",4);				//Identification
	if (!int10.vesa_oldvbe) mem_writew(buffer+0x04,0x200);	//Vesa version 2.0
	else mem_writew(buffer+0x04,0x102);						//Vesa version 1.2
	if (vbe2) {
		mem_writed(buffer+0x06,RealMake(seg,vbe2_pos));
		for (i=0;i<sizeof(string_oem);i++) real_writeb(seg,vbe2_pos++,string_oem[i]);
		mem_writew(buffer+0x14,0x200);					//VBE 2 software revision
		mem_writed(buffer+0x16,RealMake(seg,vbe2_pos));
		for (i=0;i<sizeof(string_vendorname);i++) real_writeb(seg,vbe2_pos++,string_vendorname[i]);
		mem_writed(buffer+0x1a,RealMake(seg,vbe2_pos));
		for (i=0;i<sizeof(string_productname);i++) real_writeb(seg,vbe2_pos++,string_productname[i]);
		mem_writed(buffer+0x1e,RealMake(seg,vbe2_pos));
		for (i=0;i<sizeof(string_productrev);i++) real_writeb(seg,vbe2_pos++,string_productrev[i]);
	} else {
		mem_writed(buffer+0x06,int10.rom.oemstring);	//Oemstring
	}
	mem_writed(buffer+0x0a,0x0);					//Capabilities and flags
	mem_writed(buffer+0x0e,int10.rom.vesa_modes);	//VESA Mode list
	mem_writew(buffer+0x12,(Bit16u)(vga.vmemsize/(64*1024))); // memory size in 64kb blocks
	return VESA_SUCCESS;
}
Example #5
0
static Bitu PROGRAMS_Handler(void) {
	/* This sets up everything for a program start up call */
	Bitu size=sizeof(Bit8u);
	Bit8u index;
	/* Read the index from program code in memory */
	PhysPt reader=PhysMake(dos.psp(),256+sizeof(exe_block));
	HostPt writer=(HostPt)&index;
	for (;size>0;size--) *writer++=mem_readb(reader++);
	Program * new_program = NULL;
	if (index > internal_progs.size()) E_Exit("something is messing with the memory");
	InternalProgramEntry *ipe = internal_progs[index];
	if (ipe == NULL) E_Exit("Attempt to run internal program slot with nothing allocated");
	if (ipe->main == NULL) return CBRET_NONE;
	PROGRAMS_Main * handler = internal_progs[index]->main;
	(*handler)(&new_program);

	try { /* "BOOT" can throw an exception (int(2)) */
		new_program->Run();
		delete new_program;
	}
	catch (...) { /* well if it happened, free the program anyway to avert memory leaks */
		delete new_program;
		throw; /* pass it on */
	}

	return CBRET_NONE;
}
Example #6
0
bool Program::SetEnv(const char * entry,const char * new_string) {
	PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
	PhysPt env_write=env_read;
	char env_string[1024+1];
	do 	{
		MEM_StrCopy(env_read,env_string,1024);
		if (!env_string[0]) break;
		env_read += (PhysPt)(strlen(env_string)+1);
		if (!strchr(env_string,'=')) continue;		/* Remove corrupt entry? */
		if ((strncasecmp(entry,env_string,strlen(entry))==0) && 
			env_string[strlen(entry)]=='=') continue;
		MEM_BlockWrite(env_write,env_string,(Bitu)(strlen(env_string)+1));
		env_write += (PhysPt)(strlen(env_string)+1);
	} while (1);
/* TODO Maybe save the program name sometime. not really needed though */
	/* Save the new entry */
	if (new_string[0]) {
		std::string bigentry(entry);
		for (std::string::iterator it = bigentry.begin(); it != bigentry.end(); ++it) *it = toupper(*it);
		sprintf(env_string,"%s=%s",bigentry.c_str(),new_string); 
//		sprintf(env_string,"%s=%s",entry,new_string); //oldcode
		MEM_BlockWrite(env_write,env_string,(Bitu)(strlen(env_string)+1));
		env_write += (PhysPt)(strlen(env_string)+1);
	}
	/* Clear out the final piece of the environment */
	mem_writed(env_write,0);
	return true;
}
Example #7
0
Bit8u VESA_GetSVGAInformation(Bit16u seg,Bit16u off) {
	/* Fill 256 byte buffer with VESA information */
	PhysPt buffer=PhysMake(seg,off);
	Bitu i;
	bool vbe2=false;Bit16u vbe2_pos;
	Bitu id=mem_readd(buffer);
	if (((id==0x56424532)||(id==0x32454256)) && (!int10.vesa_oldvbe)) vbe2=true;
	if (vbe2) {
		for (i=0;i<0x200;i++) mem_writeb(buffer+i,0);		
	} else {
		for (i=0;i<0x100;i++) mem_writeb(buffer+i,0);
	}
	/* Fill common data */
	MEM_BlockWrite(buffer,(void *)"VESA",4);				//Identification
	if (!int10.vesa_oldvbe) mem_writew(buffer+0x04,0x200);	//Vesa version 2.0
	else mem_writew(buffer+0x04,0x102);						//Vesa version 1.2
	if (vbe2) {
        vbe2_pos=256+off;

		mem_writed(buffer+0x06,RealMake(seg,vbe2_pos));
		for (i=0;i<sizeof(string_oem);i++) real_writeb(seg,vbe2_pos++,(Bit8u)string_oem[i]);
		mem_writew(buffer+0x14,0x200);					//VBE 2 software revision
		mem_writed(buffer+0x16,RealMake(seg,vbe2_pos));
		for (i=0;i<sizeof(string_vendorname);i++) real_writeb(seg,vbe2_pos++,(Bit8u)string_vendorname[i]);
		mem_writed(buffer+0x1a,RealMake(seg,vbe2_pos));
		for (i=0;i<sizeof(string_productname);i++) real_writeb(seg,vbe2_pos++,(Bit8u)string_productname[i]);
		mem_writed(buffer+0x1e,RealMake(seg,vbe2_pos));
		for (i=0;i<sizeof(string_productrev);i++) real_writeb(seg,vbe2_pos++,(Bit8u)string_productrev[i]);
    } else {
        vbe2_pos=0x20+off;

        mem_writed(buffer+0x06,int10.rom.oemstring);	//Oemstring
	}

    if (vesa_bios_modelist_in_info) {
        /* put the modelist into the VBE struct itself, as modern BIOSes like to do.
         * NOTICE: This limits the modelist to what is able to fit! Extended modes may not fit, which is why the option is OFF by default. */
        uint16_t modesg = int10.rom.vesa_modes >> 16;
        uint16_t modoff = int10.rom.vesa_modes & 0xFFFF;
        uint16_t m;

        mem_writed(buffer+0x0e,RealMake(seg,vbe2_pos));	//VESA Mode list

        do {
            if (vbe2) {
                if (vbe2_pos >= (509+off)) break;
            }
            else {
                if (vbe2_pos >= (253+off)) break;
            }
            m = real_readw(modesg,modoff);
            if (m == 0xFFFF) break;
            real_writew(seg,vbe2_pos,m);
            vbe2_pos += 2;
            modoff += 2;
        } while (1);
        real_writew(seg,vbe2_pos,0xFFFF);
    }
    else {
Example #8
0
Bitu Program::GetEnvCount(void) {
	PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
	Bitu num=0;
	while (mem_readb(env_read)!=0) {
		for (;mem_readb(env_read);env_read++) {};
		env_read++;
		num++;
	}
	return num;
}
static bool MakeEnv(char * name,Bit16u * segment) {
	/* If segment to copy environment is 0 copy the caller's environment */
	DOS_PSP psp(dos.psp());
	PhysPt envread,envwrite;
	Bit16u envsize=1;
	bool parentenv=true;

	if (*segment==0) {
		if (!psp.GetEnvironment()) parentenv=false;				//environment seg=0
		envread=PhysMake(psp.GetEnvironment(),0);
	} else {
		if (!*segment) parentenv=false;						//environment seg=0
		envread=PhysMake(*segment,0);
	}

	if (parentenv) {
		for (envsize=0; ;envsize++) {
			if (envsize>=MAXENV - ENV_KEEPFREE) {
				DOS_SetError(DOSERR_ENVIRONMENT_INVALID);
				return false;
			}
			if (mem_readw(envread+envsize)==0) break;
		}
		envsize += 2;									/* account for trailing \0\0 */
	}
	Bit16u size=long2para(envsize+ENV_KEEPFREE);
	if (!DOS_AllocateMemory(segment,&size)) return false;
	envwrite=PhysMake(*segment,0);
	if (parentenv) {
		MEM_BlockCopy(envwrite,envread,envsize);
//		mem_memcpy(envwrite,envread,envsize);
		envwrite+=envsize;
	} else {
		mem_writeb(envwrite++,0);
	}
	mem_writew(envwrite,1);
	envwrite+=2;
	char namebuf[DOS_PATHLENGTH];
	if (DOS_Canonicalize(name,namebuf)) {
		MEM_BlockWrite(envwrite,namebuf,strlen(namebuf)+1);
		return true;
	} else return false;
}
Example #10
0
static bool LocateEnvironmentBlock(PhysPt &env_base,PhysPt &env_fence,Bitu env_seg) {
	if (env_seg == 0) {
		/* The DOS program might have freed it's environment block perhaps. */
		return false;
	}

	DOS_MCB env_mcb(env_seg-1); /* read the environment block's MCB to determine how large it is */
	env_base = PhysMake(env_seg,0);
	env_fence = env_base + (env_mcb.GetSize() << 4);
	return true;
}
Example #11
0
bool Program::GetEnvNum(Bitu num,std::string & result) {
	char env_string[1024+1];
	PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
	do 	{
		MEM_StrCopy(env_read,env_string,1024);
		if (!env_string[0]) break;
		if (!num) { result=env_string;return true;}
		env_read += (PhysPt)(strlen(env_string)+1);
		num--;
	} while (1);
	return false;
}
Example #12
0
static Bitu PROGRAMS_Handler(void) {
	/* This sets up everything for a program start up call */
	Bitu size=sizeof(Bit8u);
	Bit8u index;
	/* Read the index from program code in memory */
	PhysPt reader=PhysMake(dos.psp(),256+sizeof(exe_block));
	HostPt writer=(HostPt)&index;
	for (;size>0;size--) *writer++=mem_readb(reader++);
	Program * new_program;
	if(index > internal_progs.size()) E_Exit("something is messing with the memory");
	PROGRAMS_Main * handler = internal_progs[index];
	(*handler)(&new_program);
	new_program->Run();
	delete new_program;
	return CBRET_NONE;
}
Example #13
0
void SVGA_Setup_ParadisePVGA1A(void) {
	svga.write_p3cf = &write_p3cf_pvga1a;
	svga.read_p3cf = &read_p3cf_pvga1a;

	svga.set_video_mode = &FinishSetMode_PVGA1A;
	svga.determine_mode = &DetermineMode_PVGA1A;
	svga.set_clock = &SetClock_PVGA1A;
	svga.get_clock = &GetClock_PVGA1A;
	svga.accepts_mode = &AcceptsMode_PVGA1A;

	VGA_SetClock(0,CLK_25);
	VGA_SetClock(1,CLK_28);
	VGA_SetClock(2,32400); // could not find documentation
	VGA_SetClock(3,35900);

	// Adjust memory, default to 512K
	if (vga.vmemsize == 0)
		vga.vmemsize = 512*1024;

	if (vga.vmemsize < 512*1024)	{
		vga.vmemsize = 256*1024;
		pvga1a.PR1 = 1<<6;
	} else if (vga.vmemsize > 512*1024) {
		vga.vmemsize = 1024*1024;
		pvga1a.PR1 = 3<<6;
	} else {
		pvga1a.PR1 = 2<<6;
	}

	// Paradise ROM signature
	PhysPt rom_base=PhysMake(0xc000,0);
	phys_writeb(rom_base+0x007d,'V');
	phys_writeb(rom_base+0x007e,'G');
	phys_writeb(rom_base+0x007f,'A');
	phys_writeb(rom_base+0x0080,'=');

	IO_Write(0x3cf, 0x05); // Enable!
}
Example #14
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);
}
Example #15
0
bool Program::GetEnvStr(const char * entry,std::string & result) {
	/* Walk through the internal environment and see for a match */
	PhysPt env_read=PhysMake(psp->GetEnvironment(),0);

	char env_string[1024+1];
	result.erase();
	if (!entry[0]) return false;
	do 	{
		MEM_StrCopy(env_read,env_string,1024);
		if (!env_string[0]) return false;
		env_read += (PhysPt)(strlen(env_string)+1);
		char* equal = strchr(env_string,'=');
		if (!equal) continue;
		/* replace the = with \0 to get the length */
		*equal = 0;
		if (strlen(env_string) != strlen(entry)) continue;
		if (strcasecmp(entry,env_string)!=0) continue;
		/* restore the = to get the original result */
		*equal = '=';
		result = env_string;
		return true;
	} while (1);
	return false;
}
Example #16
0
void MOUSE_Init(Section* /*sec*/) {
	// Callback for mouse interrupt 0x33
	call_int33=CALLBACK_Allocate();
//	RealPt i33loc=RealMake(CB_SEG+1,(call_int33*CB_SIZE)-0x10);
	RealPt i33loc=RealMake(DOS_GetMemory(0x1)-1,0x10);
	CALLBACK_Setup(call_int33,&INT33_Handler,CB_MOUSE,Real2Phys(i33loc),"Mouse");
	// Wasteland needs low(seg(int33))!=0 and low(ofs(int33))!=0
	real_writed(0,0x33<<2,i33loc);

	call_mouse_bd=CALLBACK_Allocate();
	CALLBACK_Setup(call_mouse_bd,&MOUSE_BD_Handler,CB_RETF8,
		PhysMake(RealSeg(i33loc),RealOff(i33loc)+2),"MouseBD");
	// pseudocode for CB_MOUSE (including the special backdoor entry point):
	//	jump near i33hd
	//	callback MOUSE_BD_Handler
	//	retf 8
	//  label i33hd:
	//	callback INT33_Handler
	//	iret


	// Callback for ps2 irq
	call_int74=CALLBACK_Allocate();
	CALLBACK_Setup(call_int74,&INT74_Handler,CB_IRQ12,"int 74");
	// pseudocode for CB_IRQ12:
	//	push ds
	//	push es
	//	pushad
	//	sti
	//	callback INT74_Handler
	//		doesn't return here, but rather to CB_IRQ12_RET
	//		(ps2 callback/user callback inbetween if requested)

	int74_ret_callback=CALLBACK_Allocate();
	CALLBACK_Setup(int74_ret_callback,&MOUSE_UserInt_CB_Handler,CB_IRQ12_RET,"int 74 ret");
	// pseudocode for CB_IRQ12_RET:
	//	callback MOUSE_UserInt_CB_Handler
	//	cli
	//	mov al, 0x20
	//	out 0xa0, al
	//	out 0x20, al
	//	popad
	//	pop es
	//	pop ds
	//	iret

	Bit8u hwvec=(MOUSE_IRQ>7)?(0x70+MOUSE_IRQ-8):(0x8+MOUSE_IRQ);
	RealSetVec(hwvec,CALLBACK_RealPointer(call_int74));

	// Callback for ps2 user callback handling
	useps2callback = false; ps2callbackinit = false;
 	call_ps2=CALLBACK_Allocate();
	CALLBACK_Setup(call_ps2,&PS2_Handler,CB_RETF,"ps2 bios callback");
	ps2_callback=CALLBACK_RealPointer(call_ps2);

	memset(&mouse,0,sizeof(mouse));
	mouse.hidden = 1; //Hide mouse on startup
	mouse.timer_in_progress = false;
	mouse.mode = 0xFF; //Non existing mode

   	mouse.sub_mask=0;
	mouse.sub_seg=0x6362;	// magic value
	mouse.sub_ofs=0;

	Mouse_ResetHardware();
	Mouse_Reset();
	Mouse_SetSensitivity(50,50,50);
}
Example #17
0
void SHELL_Init() {
	/* Add messages */
	MSG_Add("SHELL_ILLEGAL_PATH","Illegal Path.\n");
	MSG_Add("SHELL_CMD_HELP","If you want a list of all supported commands type \033[33;1mhelp /all\033[0m .\nA short list of the most often used commands:\n");
	MSG_Add("SHELL_CMD_ECHO_ON","ECHO is on.\n");
	MSG_Add("SHELL_CMD_ECHO_OFF","ECHO is off.\n");
	MSG_Add("SHELL_ILLEGAL_SWITCH","Illegal switch: %s.\n");
	MSG_Add("SHELL_MISSING_PARAMETER","Required parameter missing.\n");
	MSG_Add("SHELL_CMD_CHDIR_ERROR","Unable to change to: %s.\n");
	MSG_Add("SHELL_CMD_CHDIR_HINT","To change to different drive type \033[31m%c:\033[0m\n");
	MSG_Add("SHELL_CMD_CHDIR_HINT_2","directoryname is longer than 8 characters and/or contains spaces.\nTry \033[31mcd %s\033[0m\n");
	MSG_Add("SHELL_CMD_CHDIR_HINT_3","You are still on drive Z:, change to a mounted drive with \033[31mC:\033[0m.\n");
	MSG_Add("SHELL_CMD_MKDIR_ERROR","Unable to make: %s.\n");
	MSG_Add("SHELL_CMD_RMDIR_ERROR","Unable to remove: %s.\n");
	MSG_Add("SHELL_CMD_DEL_ERROR","Unable to delete: %s.\n");
	MSG_Add("SHELL_SYNTAXERROR","The syntax of the command is incorrect.\n");
	MSG_Add("SHELL_CMD_SET_NOT_SET","Environment variable %s not defined.\n");
	MSG_Add("SHELL_CMD_SET_OUT_OF_SPACE","Not enough environment space left.\n");
	MSG_Add("SHELL_CMD_IF_EXIST_MISSING_FILENAME","IF EXIST: Missing filename.\n");
	MSG_Add("SHELL_CMD_IF_ERRORLEVEL_MISSING_NUMBER","IF ERRORLEVEL: Missing number.\n");
	MSG_Add("SHELL_CMD_IF_ERRORLEVEL_INVALID_NUMBER","IF ERRORLEVEL: Invalid number.\n");
	MSG_Add("SHELL_CMD_GOTO_MISSING_LABEL","No label supplied to GOTO command.\n");
	MSG_Add("SHELL_CMD_GOTO_LABEL_NOT_FOUND","GOTO: Label %s not found.\n");
	MSG_Add("SHELL_CMD_FILE_NOT_FOUND","File %s not found.\n");
	MSG_Add("SHELL_CMD_FILE_EXISTS","File %s already exists.\n");
	MSG_Add("SHELL_CMD_DIR_INTRO","Directory of %s.\n");
	MSG_Add("SHELL_CMD_DIR_BYTES_USED","%5d File(s) %17s Bytes.\n");
	MSG_Add("SHELL_CMD_DIR_BYTES_FREE","%5d Dir(s)  %17s Bytes free.\n");
	MSG_Add("SHELL_EXECUTE_DRIVE_NOT_FOUND","Drive %c does not exist!\nYou must \033[31mmount\033[0m it first. Type \033[1;33mintro\033[0m or \033[1;33mintro mount\033[0m for more information.\n");
	MSG_Add("SHELL_EXECUTE_ILLEGAL_COMMAND","Illegal command: %s.\n");
	MSG_Add("SHELL_CMD_PAUSE","Press any key to continue.\n");
	MSG_Add("SHELL_CMD_PAUSE_HELP","Waits for 1 keystroke to continue.\n");
	MSG_Add("SHELL_CMD_COPY_FAILURE","Copy failure : %s.\n");
	MSG_Add("SHELL_CMD_COPY_SUCCESS","   %d File(s) copied.\n");
	MSG_Add("SHELL_CMD_SUBST_NO_REMOVE","Removing drive not supported. Doing nothing.\n");
	MSG_Add("SHELL_CMD_SUBST_FAILURE","SUBST failed. You either made an error in your commandline or the target drive is already used.\nIt's only possible to use SUBST on Local drives");

	MSG_Add("SHELL_STARTUP_BEGIN",
		"\033[44;1m\xC9\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
		"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
		"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBB\n"
		"\xBA \033[32mWelcome to DOSBox v%-8s\033[37m                                        \xBA\n"
		"\xBA                                                                    \xBA\n"
//		"\xBA DOSBox runs real and protected mode games.                         \xBA\n"
		"\xBA For a short introduction for new users type: \033[33mINTRO\033[37m                 \xBA\n"
		"\xBA For supported shell commands type: \033[33mHELP\033[37m                            \xBA\n"
		"\xBA                                                                    \xBA\n"
		"\xBA To adjust the emulated CPU speed, use \033[31mctrl-F11\033[37m and \033[31mctrl-F12\033[37m.       \xBA\n"
		"\xBA To activate the keymapper \033[31mctrl-F1\033[37m.                                 \xBA\n"
		"\xBA For more information read the \033[36mREADME\033[37m file in the DOSBox directory. \xBA\n"
		"\xBA                                                                    \xBA\n"
	);
	MSG_Add("SHELL_STARTUP_CGA","\xBA DOSBox supports Composite CGA mode.                                \xBA\n"
	        "\xBA Use \033[31m(alt-)F11\033[37m to change the colours when in this mode.             \xBA\n"
	        "\xBA                                                                    \xBA\n"
	);
	MSG_Add("SHELL_STARTUP_HERC","\xBA Use \033[31mF11\033[37m to cycle through white, amber, and green monochrome color. \xBA\n"
	        "\xBA                                                                    \xBA\n"
	);
	MSG_Add("SHELL_STARTUP_DEBUG",
	        "\xBA Press \033[31malt-Pause\033[37m to enter the debugger or start the exe with \033[33mDEBUG\033[37m. \xBA\n"
	        "\xBA                                                                    \xBA\n"
	);
	MSG_Add("SHELL_STARTUP_END",
	        "\xBA \033[32mHAVE FUN!\033[37m                                                          \xBA\n"
	        "\xBA \033[32mThe DOSBox Team \033[33mhttp://www.dosbox.com\033[37m                              \xBA\n"
	        "\xC8\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
	        "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
	        "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBC\033[0m\n"
	        //"\n" //Breaks the startup message if you type a mount and a drive change.
	);
	MSG_Add("SHELL_CMD_CHDIR_HELP","Displays/changes the current directory.\n");
	MSG_Add("SHELL_CMD_CHDIR_HELP_LONG","CHDIR [drive:][path]\n"
	        "CHDIR [..]\n"
	        "CD [drive:][path]\n"
	        "CD [..]\n\n"
	        "  ..   Specifies that you want to change to the parent directory.\n\n"
	        "Type CD drive: to display the current directory in the specified drive.\n"
	        "Type CD without parameters to display the current drive and directory.\n");
	MSG_Add("SHELL_CMD_CLS_HELP","Clear screen.\n");
	MSG_Add("SHELL_CMD_DIR_HELP","Directory View.\n");
	MSG_Add("SHELL_CMD_ECHO_HELP","Display messages and enable/disable command echoing.\n");
	MSG_Add("SHELL_CMD_EXIT_HELP","Exit from the shell.\n");
	MSG_Add("SHELL_CMD_HELP_HELP","Show help.\n");
	MSG_Add("SHELL_CMD_MKDIR_HELP","Make Directory.\n");
	MSG_Add("SHELL_CMD_MKDIR_HELP_LONG","MKDIR [drive:][path]\n"
	        "MD [drive:][path]\n");
	MSG_Add("SHELL_CMD_RMDIR_HELP","Remove Directory.\n");
	MSG_Add("SHELL_CMD_RMDIR_HELP_LONG","RMDIR [drive:][path]\n"
	        "RD [drive:][path]\n");
	MSG_Add("SHELL_CMD_SET_HELP","Change environment variables.\n");
	MSG_Add("SHELL_CMD_IF_HELP","Performs conditional processing in batch programs.\n");
	MSG_Add("SHELL_CMD_GOTO_HELP","Jump to a labeled line in a batch script.\n");
	MSG_Add("SHELL_CMD_SHIFT_HELP","Leftshift commandline parameters in a batch script.\n");
	MSG_Add("SHELL_CMD_TYPE_HELP","Display the contents of a text-file.\n");
	MSG_Add("SHELL_CMD_TYPE_HELP_LONG","TYPE [drive:][path][filename]\n");
	MSG_Add("SHELL_CMD_REM_HELP","Add comments in a batch file.\n");
	MSG_Add("SHELL_CMD_REM_HELP_LONG","REM [comment]\n");
	MSG_Add("SHELL_CMD_NO_WILD","This is a simple version of the command, no wildcards allowed!\n");
	MSG_Add("SHELL_CMD_RENAME_HELP","Renames one or more files.\n");
	MSG_Add("SHELL_CMD_RENAME_HELP_LONG","RENAME [drive:][path]filename1 filename2.\n"
	        "REN [drive:][path]filename1 filename2.\n\n"
	        "Note that you can not specify a new drive or path for your destination file.\n");
	MSG_Add("SHELL_CMD_DELETE_HELP","Removes one or more files.\n");
	MSG_Add("SHELL_CMD_COPY_HELP","Copy files.\n");
	MSG_Add("SHELL_CMD_CALL_HELP","Start a batch file from within another batch file.\n");
	MSG_Add("SHELL_CMD_SUBST_HELP","Assign an internal directory to a drive.\n");
	MSG_Add("SHELL_CMD_LOADHIGH_HELP","Loads a program into upper memory (requires xms=true,umb=true).\n");
	MSG_Add("SHELL_CMD_CHOICE_HELP","Waits for a keypress and sets ERRORLEVEL.\n");
	MSG_Add("SHELL_CMD_CHOICE_HELP_LONG","CHOICE [/C:choices] [/N] [/S] text\n"
	        "  /C[:]choices  -  Specifies allowable keys.  Default is: yn.\n"
	        "  /N  -  Do not display the choices at end of prompt.\n"
	        "  /S  -  Enables case-sensitive choices to be selected.\n"
	        "  text  -  The text to display as a prompt.\n");
	MSG_Add("SHELL_CMD_ATTRIB_HELP","Does nothing. Provided for compatibility.\n");
	MSG_Add("SHELL_CMD_PATH_HELP","Provided for compatibility.\n");
	MSG_Add("SHELL_CMD_VER_HELP","View and set the reported DOS version.\n");
	MSG_Add("SHELL_CMD_VER_VER","DOSBox version %s. Reported DOS version %d.%02d.\n");
#ifdef IPHONEOS
        MSG_Add("SHELL_CMD_UNZIP_HELP","Extract zip file to current directory.\n");
#endif
	/* Regular startup */
	call_shellstop=CALLBACK_Allocate();
	/* Setup the startup CS:IP to kill the last running machine when exitted */
	RealPt newcsip=CALLBACK_RealPointer(call_shellstop);
	SegSet16(cs,RealSeg(newcsip));
	reg_ip=RealOff(newcsip);

	CALLBACK_Setup(call_shellstop,shellstop_handler,CB_IRET,"shell stop");
	PROGRAMS_MakeFile("COMMAND.COM",SHELL_ProgramStart);

	/* Now call up the shell for the first time */
	Bit16u psp_seg=DOS_FIRST_SHELL;
	Bit16u env_seg=DOS_FIRST_SHELL+19; //DOS_GetMemory(1+(4096/16))+1;
	Bit16u stack_seg=DOS_GetMemory(2048/16);
	SegSet16(ss,stack_seg);
	reg_sp=2046;

	/* Set up int 24 and psp (Telarium games) */
	real_writeb(psp_seg+16+1,0,0xea);		/* far jmp */
	real_writed(psp_seg+16+1,1,real_readd(0,0x24*4));
	real_writed(0,0x24*4,((Bit32u)psp_seg<<16) | ((16+1)<<4));

	/* Set up int 23 to "int 20" in the psp. Fixes what.exe */
	real_writed(0,0x23*4,((Bit32u)psp_seg<<16));

	/* Setup MCBs */
	DOS_MCB pspmcb((Bit16u)(psp_seg-1));
	pspmcb.SetPSPSeg(psp_seg);	// MCB of the command shell psp
	pspmcb.SetSize(0x10+2);
	pspmcb.SetType(0x4d);
	DOS_MCB envmcb((Bit16u)(env_seg-1));
	envmcb.SetPSPSeg(psp_seg);	// MCB of the command shell environment
	envmcb.SetSize(DOS_MEM_START-env_seg);
	envmcb.SetType(0x4d);
	
	/* Setup environment */
	PhysPt env_write=PhysMake(env_seg,0);
	MEM_BlockWrite(env_write,path_string,(Bitu)(strlen(path_string)+1));
	env_write += (PhysPt)(strlen(path_string)+1);
	MEM_BlockWrite(env_write,comspec_string,(Bitu)(strlen(comspec_string)+1));
	env_write += (PhysPt)(strlen(comspec_string)+1);
	mem_writeb(env_write++,0);
	mem_writew(env_write,1);
	env_write+=2;
	MEM_BlockWrite(env_write,full_name,(Bitu)(strlen(full_name)+1));

	DOS_PSP psp(psp_seg);
	psp.MakeNew(0);
	dos.psp(psp_seg);
   
	/* The start of the filetable in the psp must look like this:
	 * 01 01 01 00 02
	 * In order to achieve this: First open 2 files. Close the first and
	 * duplicate the second (so the entries get 01) */
	Bit16u dummy=0;
	DOS_OpenFile("CON",OPEN_READWRITE,&dummy);	/* STDIN  */
	DOS_OpenFile("CON",OPEN_READWRITE,&dummy);	/* STDOUT */
	DOS_CloseFile(0);							/* Close STDIN */
	DOS_ForceDuplicateEntry(1,0);				/* "new" STDIN */
	DOS_ForceDuplicateEntry(1,2);				/* STDERR */
	DOS_OpenFile("CON",OPEN_READWRITE,&dummy);	/* STDAUX */
	DOS_OpenFile("CON",OPEN_READWRITE,&dummy);	/* STDPRN */

	psp.SetParent(psp_seg);
	/* Set the environment */
	psp.SetEnvironment(env_seg);
	/* Set the command line for the shell start up */
	CommandTail tail;
	tail.count=(Bit8u)strlen(init_line);
	strcpy(tail.buffer,init_line);
	MEM_BlockWrite(PhysMake(psp_seg,128),&tail,128);
	
	/* Setup internal DOS Variables */
	dos.dta(RealMake(psp_seg,0x80));
	dos.psp(psp_seg);

	
	SHELL_ProgramStart(&first_shell);
	first_shell->Run();
	delete first_shell;
	first_shell = 0;//Make clear that it shouldn't be used anymore
}
Example #18
0
void DOS_InfoBlock::SetLocation(Bit16u segment) {
	seg = segment;
	pt=PhysMake(seg,0);
	/* Clear the initial Block */
	for(Bitu i=0;i<sizeof(sDIB);i++) mem_writeb(pt+i,0xff);
	for(Bitu i=0;i<14;i++) mem_writeb(pt+i,0);

	sSave(sDIB,regCXfrom5e,(Bit16u)0);
	sSave(sDIB,countLRUcache,(Bit16u)0);
	sSave(sDIB,countLRUopens,(Bit16u)0);

	sSave(sDIB,protFCBs,(Bit16u)0);
	sSave(sDIB,specialCodeSeg,(Bit16u)0);
	sSave(sDIB,joindedDrives,(Bit8u)0);
	sSave(sDIB,lastdrive,(Bit8u)0x01);//increase this if you add drives to cds-chain

	sSave(sDIB,diskInfoBuffer,RealMake(segment,offsetof(sDIB,diskBufferHeadPt)));
	sSave(sDIB,setverPtr,(Bit32u)0);

	sSave(sDIB,a20FixOfs,(Bit16u)0);
	sSave(sDIB,pspLastIfHMA,(Bit16u)0);
	sSave(sDIB,blockDevices,(Bit8u)0);
	
	sSave(sDIB,bootDrive,(Bit8u)0);
	sSave(sDIB,useDwordMov,(Bit8u)1);
	sSave(sDIB,extendedSize,(Bit16u)(MEM_TotalPages()*4-1024));
	sSave(sDIB,magicWord,(Bit16u)0x0001);		// dos5+

	sSave(sDIB,sharingCount,(Bit16u)0);
	sSave(sDIB,sharingDelay,(Bit16u)0);
	sSave(sDIB,ptrCONinput,(Bit16u)0);			// no unread input available
	sSave(sDIB,maxSectorLength,(Bit16u)0x200);

	sSave(sDIB,dirtyDiskBuffers,(Bit16u)0);
	sSave(sDIB,lookaheadBufPt,(Bit32u)0);
	sSave(sDIB,lookaheadBufNumber,(Bit16u)0);
	sSave(sDIB,bufferLocation,(Bit8u)0);		// buffer in base memory, no workspace
	sSave(sDIB,workspaceBuffer,(Bit32u)0);

	sSave(sDIB,minMemForExec,(Bit16u)0);
	sSave(sDIB,memAllocScanStart,(Bit16u)DOS_MEM_START);
	sSave(sDIB,startOfUMBChain,(Bit16u)0xffff);
	sSave(sDIB,chainingUMB,(Bit8u)0);

	sSave(sDIB,nulNextDriver,(Bit32u)0xffffffff);
	sSave(sDIB,nulAttributes,(Bit16u)0x8004);
	sSave(sDIB,nulStrategy,(Bit32u)0x00000000);
	sSave(sDIB,nulString[0],(Bit8u)0x4e);
	sSave(sDIB,nulString[1],(Bit8u)0x55);
	sSave(sDIB,nulString[2],(Bit8u)0x4c);
	sSave(sDIB,nulString[3],(Bit8u)0x20);
	sSave(sDIB,nulString[4],(Bit8u)0x20);
	sSave(sDIB,nulString[5],(Bit8u)0x20);
	sSave(sDIB,nulString[6],(Bit8u)0x20);
	sSave(sDIB,nulString[7],(Bit8u)0x20);

	/* Create a fake SFT, so programs think there are 100 file handles */
	Bit16u sftOffset=offsetof(sDIB,firstFileTable)+0xa2;
	sSave(sDIB,firstFileTable,RealMake(segment,sftOffset));
	real_writed(segment,sftOffset+0x00,RealMake(segment+0x26,0));	//Next File Table
	real_writew(segment,sftOffset+0x04,100);		//File Table supports 100 files
	real_writed(segment+0x26,0x00,0xffffffff);		//Last File Table
	real_writew(segment+0x26,0x04,100);				//File Table supports 100 files
}
Example #19
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;
}
Example #20
0
bool device_EMM::ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode) { 
	Bitu subfct=mem_readb(bufptr);
	switch (subfct) {
		case 0x00:
			if (size!=6) return false;
			mem_writew(bufptr+0x00,0x0023);		// ID
			mem_writed(bufptr+0x02,0);			// private API entry point
			*retcode=6;
			return true;
		case 0x01: {
			if (size!=6) return false;
			if (GEMMIS_seg==0) GEMMIS_seg=DOS_GetMemory(0x20);
			PhysPt GEMMIS_addr=PhysMake(GEMMIS_seg,0);

			mem_writew(GEMMIS_addr+0x00,0x0004);			// flags
			mem_writew(GEMMIS_addr+0x02,0x019d);			// size of this structure
			mem_writew(GEMMIS_addr+0x04,GEMMIS_VERSION);	// version 1.0 (provide ems information only)
			mem_writed(GEMMIS_addr+0x06,0);					// reserved

			/* build non-EMS frames (0-0xe000) */
			for (Bitu frct=0; frct<EMM_PAGEFRAME4K/4; frct++) {
				mem_writeb(GEMMIS_addr+0x0a+frct*6,0x00);	// frame type: NONE
				mem_writeb(GEMMIS_addr+0x0b+frct*6,0xff);	// owner: NONE
				mem_writew(GEMMIS_addr+0x0c+frct*6,0xffff);	// non-EMS frame
				mem_writeb(GEMMIS_addr+0x0e + frct*6,0xff);	// EMS page number (NONE)
				mem_writeb(GEMMIS_addr+0x0f+frct*6,0xaa);	// flags: direct mapping
			}
			/* build EMS page frame (0xe000-0xf000) */
			for (Bitu frct=0; frct<0x10/4; frct++) {
				Bitu frnr=(frct+EMM_PAGEFRAME4K/4)*6;
				mem_writeb(GEMMIS_addr+0x0a+frnr,0x03);		// frame type: EMS frame in 64k page
				mem_writeb(GEMMIS_addr+0x0b+frnr,0xff);		// owner: NONE
				mem_writew(GEMMIS_addr+0x0c+frnr,0x7fff);	// no logical page number
				mem_writeb(GEMMIS_addr+0x0e + frnr,(Bit8u)(frct&0xff));		// physical EMS page number
				mem_writeb(GEMMIS_addr+0x0f+frnr,0x00);		// EMS frame
			}
			/* build non-EMS ROM frames (0xf000-0x10000) */
			for (Bitu frct=(EMM_PAGEFRAME4K+0x10)/4; frct<0xf0/4; frct++) {
				mem_writeb(GEMMIS_addr+0x0a+frct*6,0x00);	// frame type: NONE
				mem_writeb(GEMMIS_addr+0x0b+frct*6,0xff);	// owner: NONE
				mem_writew(GEMMIS_addr+0x0c+frct*6,0xffff);	// non-EMS frame
				mem_writeb(GEMMIS_addr+0x0e + frct*6,0xff);	// EMS page number (NONE)
				mem_writeb(GEMMIS_addr+0x0f+frct*6,0xaa);	// flags: direct mapping
			}

			mem_writeb(GEMMIS_addr+0x18a,0x74);			// ???
			mem_writeb(GEMMIS_addr+0x18b,0x00);			// no UMB descriptors following
			mem_writeb(GEMMIS_addr+0x18c,0x01);			// 1 EMS handle info recort
			mem_writew(GEMMIS_addr+0x18d,0x0000);		// system handle
			mem_writed(GEMMIS_addr+0x18f,0);			// handle name
			mem_writed(GEMMIS_addr+0x193,0);			// handle name
			mem_writew(GEMMIS_addr+0x197,0x0010);		// system handle
			mem_writed(GEMMIS_addr+0x199,0x00110000);	// physical address

			/* fill buffer with import structure */
			mem_writed(bufptr+0x00,GEMMIS_seg<<4);
			mem_writew(bufptr+0x04,GEMMIS_VERSION);
			*retcode=6;
			return true;
			}
		case 0x02:
			if (size!=2) return false;
			mem_writeb(bufptr+0x00,EMM_VERSION>>4);		// version 4.0
			mem_writew(bufptr+0x01,EMM_VERSION&0x0f);
			*retcode=2;
			return true;
	}
	return false;
}
Example #21
0
Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change) {
	char * string_begin=string;
	Bit8u ret=0;
	if (!(parser & PARSE_DFLT_DRIVE)) {
		// default drive forced, this intentionally invalidates an extended FCB
		mem_writeb(PhysMake(seg,offset),0);
	}
	DOS_FCB fcb(seg,offset,false);	// always a non-extended FCB
	bool hasdrive,hasname,hasext,finished;
	hasdrive=hasname=hasext=finished=false;
	Bitu index=0;
	Bit8u fill=' ';
/* First get the old data from the fcb */
#ifdef _MSC_VER
#pragma pack (1)
#endif
	union {
		struct {
			char drive[2];
			char name[9];
			char ext[4];
		} GCC_ATTRIBUTE (packed) part;
		char full[DOS_FCBNAME];
	} fcb_name;
#ifdef _MSC_VER
#pragma pack()
#endif
	/* Get the old information from the previous fcb */
	fcb.GetName(fcb_name.full);
	fcb_name.part.drive[0]-='A'-1;fcb_name.part.drive[1]=0;
	fcb_name.part.name[8]=0;fcb_name.part.ext[3]=0;
	/* Strip of the leading sepetaror */
	if((parser & PARSE_SEP_STOP) && *string)  {       //ignore leading seperator
		char sep[] = FCB_SEP;char a[2];
		a[0]= *string;a[1]='\0';
		if (strcspn(a,sep)==0) string++;
	} 
	/* strip leading spaces */
	while((*string==' ')||(*string=='\t')) string++;
	/* Check for a drive */
	if (string[1]==':') {
		fcb_name.part.drive[0]=0;
		hasdrive=true;
		if (isalpha(string[0]) && Drives[toupper(string[0])-'A']) {
			fcb_name.part.drive[0]=(char)(toupper(string[0])-'A'+1);
		} else ret=0xff;
		string+=2;
	}
	/* Special checks for . and .. */
	if (string[0]=='.') {
		string++;
		if (!string[0])	{
			hasname=true;
			ret=PARSE_RET_NOWILD;
			strcpy(fcb_name.part.name,".       ");
			goto savefcb;
		}
		if (string[1]=='.' && !string[1])	{
			string++;
			hasname=true;
			ret=PARSE_RET_NOWILD;
			strcpy(fcb_name.part.name,"..      ");
			goto savefcb;
		}
		goto checkext;
	}
	/* Copy the name */	
	hasname=true;finished=false;fill=' ';index=0;
	while (index<8) {
		if (!finished) {
			if (string[0]=='*') {fill='?';fcb_name.part.name[index]='?';if (!ret) ret=1;finished=true;}
			else if (string[0]=='?') {fcb_name.part.name[index]='?';if (!ret) ret=1;}
			else if (isvalid(string[0])) {fcb_name.part.name[index]=(char)(toupper(string[0]));}
			else { finished=true;continue; }
			string++;
		} else {
			fcb_name.part.name[index]=fill;
		}
		index++;
	}
	if (!(string[0]=='.')) goto savefcb;
	string++;
checkext:
	/* Copy the extension */
	hasext=true;finished=false;fill=' ';index=0;
	while (index<3) {
		if (!finished) {
			if (string[0]=='*') {fill='?';fcb_name.part.ext[index]='?';finished=true;}
			else if (string[0]=='?') {fcb_name.part.ext[index]='?';if (!ret) ret=1;}
			else if (isvalid(string[0])) {fcb_name.part.ext[index]=(char)(toupper(string[0]));}
			else { finished=true;continue; }
			string++;
		} else {
			fcb_name.part.ext[index]=fill;
		}
		index++;
	}
savefcb:
	if (!hasdrive & !(parser & PARSE_DFLT_DRIVE)) fcb_name.part.drive[0] = 0;
	if (!hasname & !(parser & PARSE_BLNK_FNAME)) strcpy(fcb_name.part.name,"        ");
	if (!hasext & !(parser & PARSE_BLNK_FEXT)) strcpy(fcb_name.part.ext,"   ");
	fcb.SetName(fcb_name.part.drive[0],fcb_name.part.name,fcb_name.part.ext);
	*change=(Bit8u)(string-string_begin);
	return ret;
}
Example #22
0
Bit8u VESA_GetSVGAModeInformation(Bit16u mode,Bit16u seg,Bit16u off) {
	MODE_INFO minfo;
	memset(&minfo,0,sizeof(minfo));
	PhysPt buf=PhysMake(seg,off);
	Bitu pageSize;
	Bit8u modeAttributes;
	Bitu i=0;

	mode&=0x3fff;	// vbe2 compatible, ignore lfb and keep screen content bits
	if (mode<0x100) return 0x01;
	if (svga.accepts_mode) {
		if (!svga.accepts_mode(mode)) return 0x01;
	}
	while (ModeList_VGA[i].mode!=0xffff) {
		if (mode==ModeList_VGA[i].mode) goto foundit; else i++;
	}
	return VESA_FAIL;
foundit:
	if ((int10.vesa_oldvbe) && (ModeList_VGA[i].mode>=0x120)) return 0x01;
	VideoModeBlock * mblock=&ModeList_VGA[i];
	switch (mblock->type) {
	case M_LIN4:
		pageSize = mblock->sheight * mblock->swidth/2;
		var_write(&minfo.BytesPerScanLine,mblock->swidth/8);
		var_write(&minfo.NumberOfPlanes,0x4);
		var_write(&minfo.BitsPerPixel,4);
		var_write(&minfo.MemoryModel,3);	//ega planar mode
		modeAttributes = 0x1b;	// Color, graphics, no linear buffer
		break;
	case M_LIN8:
		pageSize = mblock->sheight * mblock->swidth;
		var_write(&minfo.BytesPerScanLine,mblock->swidth);
		var_write(&minfo.NumberOfPlanes,0x1);
		var_write(&minfo.BitsPerPixel,8);
		var_write(&minfo.MemoryModel,4);		//packed pixel
		modeAttributes = 0x1b;	// Color, graphics
		if (!int10.vesa_nolfb) modeAttributes |= 0x80;	// linear framebuffer
		break;
	case M_LIN15:
		pageSize = mblock->sheight * mblock->swidth*2;
		var_write(&minfo.BytesPerScanLine,mblock->swidth*2);
		var_write(&minfo.NumberOfPlanes,0x1);
		var_write(&minfo.BitsPerPixel,15);
		var_write(&minfo.MemoryModel,6);	//HiColour
		var_write(&minfo.RedMaskSize,5);
		var_write(&minfo.RedMaskPos,10);
		var_write(&minfo.GreenMaskSize,5);
		var_write(&minfo.GreenMaskPos,5);
		var_write(&minfo.BlueMaskSize,5);
		var_write(&minfo.BlueMaskPos,0);
		var_write(&minfo.ReservedMaskSize,0x01);
		var_write(&minfo.ReservedMaskPos,0x0f);
		modeAttributes = 0x1b;	// Color, graphics
		if (!int10.vesa_nolfb) modeAttributes |= 0x80;	// linear framebuffer
		break;
	case M_LIN16:
		pageSize = mblock->sheight * mblock->swidth*2;
		var_write(&minfo.BytesPerScanLine,mblock->swidth*2);
		var_write(&minfo.NumberOfPlanes,0x1);
		var_write(&minfo.BitsPerPixel,16);
		var_write(&minfo.MemoryModel,6);	//HiColour
		var_write(&minfo.RedMaskSize,5);
		var_write(&minfo.RedMaskPos,11);
		var_write(&minfo.GreenMaskSize,6);
		var_write(&minfo.GreenMaskPos,5);
		var_write(&minfo.BlueMaskSize,5);
		var_write(&minfo.BlueMaskPos,0);
		modeAttributes = 0x1b;	// Color, graphics
		if (!int10.vesa_nolfb) modeAttributes |= 0x80;	// linear framebuffer
		break;
	case M_LIN32:
		pageSize = mblock->sheight * mblock->swidth*4;
		var_write(&minfo.BytesPerScanLine,mblock->swidth*4);
		var_write(&minfo.NumberOfPlanes,0x1);
		var_write(&minfo.BitsPerPixel,32);
		var_write(&minfo.MemoryModel,6);	//HiColour
		var_write(&minfo.RedMaskSize,8);
		var_write(&minfo.RedMaskPos,0x10);
		var_write(&minfo.GreenMaskSize,0x8);
		var_write(&minfo.GreenMaskPos,0x8);
		var_write(&minfo.BlueMaskSize,0x8);
		var_write(&minfo.BlueMaskPos,0x0);
		var_write(&minfo.ReservedMaskSize,0x8);
		var_write(&minfo.ReservedMaskPos,0x18);
		modeAttributes = 0x1b;	// Color, graphics
		if (!int10.vesa_nolfb) modeAttributes |= 0x80;	// linear framebuffer
		break;
	case M_TEXT:
		pageSize = 0;
		var_write(&minfo.BytesPerScanLine, mblock->twidth * 2);
		var_write(&minfo.NumberOfPlanes,0x4);
		var_write(&minfo.BitsPerPixel,4);
		var_write(&minfo.MemoryModel,0);	// text
		modeAttributes = 0x0f;	//Color, text, bios output
		break;
	default:
		return VESA_FAIL;
	}
	if (pageSize & 0xFFFF) {
		// It is documented that many applications assume 64k-aligned page sizes
		// VBETEST is one of them
		pageSize += 0x10000;
		pageSize &= ~0xFFFF;
	}
	Bitu pages = 0;
	if (pageSize > vga.vmemsize) {
		// mode not supported by current hardware configuration
		modeAttributes &= ~0x1;
	} else if (pageSize) {
		pages = (vga.vmemsize / pageSize)-1;
	}
	var_write(&minfo.NumberOfImagePages, pages);
	var_write(&minfo.ModeAttributes, modeAttributes);
	var_write(&minfo.WinAAttributes, 0x7);	// Exists/readable/writable

	if (mblock->type==M_TEXT) {
		var_write(&minfo.WinGranularity,32);
		var_write(&minfo.WinSize,32);
		var_write(&minfo.WinASegment,0xb800);
		var_write(&minfo.XResolution,mblock->twidth);
		var_write(&minfo.YResolution,mblock->theight);
	} else {
		var_write(&minfo.WinGranularity,64);
		var_write(&minfo.WinSize,64);
		var_write(&minfo.WinASegment,0xa000);
		var_write(&minfo.XResolution,mblock->swidth);
		var_write(&minfo.YResolution,mblock->sheight);
	}
	var_write(&minfo.WinFuncPtr,CALLBACK_RealPointer(callback.setwindow));
	var_write(&minfo.NumberOfBanks,0x1);
	var_write(&minfo.Reserved_page,0x1);
	var_write(&minfo.XCharSize,mblock->cwidth);
	var_write(&minfo.YCharSize,mblock->cheight);
	if (!int10.vesa_nolfb) var_write(&minfo.PhysBasePtr,S3_LFB_BASE);

	MEM_BlockWrite(buf,&minfo,sizeof(MODE_INFO));
	return VESA_SUCCESS;
}
Example #23
0
Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change) {
    char * string_begin=string;
    Bit8u ret=0;
    if (!(parser & PARSE_DFLT_DRIVE)) {
        // default drive forced, this intentionally invalidates an extended FCB
        mem_writeb(PhysMake(seg,offset),0);
    }
    DOS_FCB fcb(seg,offset,false);	// always a non-extended FCB
    bool hasdrive,hasname,hasext,finished;
    hasdrive=hasname=hasext=finished=false;
    Bitu index=0;
    Bit8u fill=' ';
    /* First get the old data from the fcb */
#ifdef _MSC_VER
#pragma pack (1)
#endif
    union {
        struct {
            char drive[2];
            char name[9];
            char ext[4];
        } GCC_ATTRIBUTE (packed) part;
        char full[DOS_FCBNAME];
    } fcb_name;
#ifdef _MSC_VER
#pragma pack()
#endif
    /* Get the old information from the previous fcb */
    fcb.GetName(fcb_name.full);
    fcb_name.part.drive[0]-='A'-1;
    fcb_name.part.drive[1]=0;
    fcb_name.part.name[8]=0;
    fcb_name.part.ext[3]=0;
    /* strip leading spaces */
    while((*string==' ')||(*string=='\t')) string++;

    /* Strip of the leading separator */
    if((parser & PARSE_SEP_STOP) && *string) {
        char sep[] = FCB_SEP;
        char a[2];
        a[0] = *string;
        a[1] = '\0';
        if (strcspn(a,sep) == 0) string++;
    }

    /* Skip following spaces as well */
    while((*string==' ')||(*string=='\t')) string++;

    /* Check for a drive */
    if (string[1]==':') {
        unsigned char d = *reinterpret_cast<unsigned char*>(&string[0]);
        if (!isvalid(toupper(d))) {
            string += 2;    //TODO check (for ret value)
            goto savefcb;
        }
        fcb_name.part.drive[0]=0;
        hasdrive=true;
        if (isalpha(d) && Drives[toupper(d)-'A']) { //Floppies under dos always exist, but don't bother with that at this level
            ; //THIS* was here
        } else ret=0xff;
        fcb_name.part.drive[0]=DOS_ToUpper(string[0])-'A'+1; //Always do THIS* and continue parsing, just return the right code
        string+=2;
    }

    /* Check for extension only file names */
    if (string[0] == '.') {
        string++;
        goto checkext;
    }

    /* do nothing if not a valid name */
    if(!isvalid(string[0])) goto savefcb;

    hasname=true;
    finished=false;
    fill=' ';
    index=0;
    /* Copy the name */
    while (true) {
        unsigned char nc = *reinterpret_cast<unsigned char*>(&string[0]);
        char ncs = (char)toupper(nc); //Should use DOS_ToUpper, but then more calls need to be changed.
        if (ncs == '*') { //Handle *
            fill = '?';
            ncs = '?';
        }
        if (ncs == '?' && !ret && index < 8) ret = 1; //Don't override bad drive
        if (!isvalid(ncs)) { //Fill up the name.
            while(index < 8)
                fcb_name.part.name[index++] = fill;
            break;
        }
        if (index < 8) {
            fcb_name.part.name[index++] = (fill == '?')?fill:ncs;
        }
        string++;
    }
    if (!(string[0]=='.')) goto savefcb;
    string++;
checkext:
    /* Copy the extension */
    hasext=true;
    finished=false;
    fill=' ';
    index=0;
    while (true) {
        unsigned char nc = *reinterpret_cast<unsigned char*>(&string[0]);
        char ncs = (char)toupper(nc);
        if (ncs == '*') { //Handle *
            fill = '?';
            ncs = '?';
        }
        if (ncs == '?' && !ret && index < 3) ret = 1;
        if (!isvalid(ncs)) { //Fill up the name.
            while(index < 3)
                fcb_name.part.ext[index++] = fill;
            break;
        }
        if (index < 3) {
            fcb_name.part.ext[index++] = (fill=='?')?fill:ncs;
        }
        string++;
    }
savefcb:
    if (!hasdrive & !(parser & PARSE_DFLT_DRIVE)) fcb_name.part.drive[0] = 0;
    if (!hasname & !(parser & PARSE_BLNK_FNAME)) strcpy(fcb_name.part.name,"        ");
    if (!hasext & !(parser & PARSE_BLNK_FEXT)) strcpy(fcb_name.part.ext,"   ");
    fcb.SetName(fcb_name.part.drive[0],fcb_name.part.name,fcb_name.part.ext);
    fcb.ClearBlockRecsize(); //Undocumented bonus work.
    *change=(Bit8u)(string-string_begin);
    return ret;
}
Example #24
0
void DOS_PSP::SetFCB2(RealPt src) {
	if (src) MEM_BlockCopy(PhysMake(seg,offsetof(sPSP,fcb2)),Real2Phys(src),16);
}
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;
}
Example #26
0
bool DOS_IOCTL(void) {
	Bitu handle=0;Bit8u drive=0;
	/* calls 0-4,6,7,10,12,16 use a file handle */
	if ((reg_al<4) || (reg_al==0x06) || (reg_al==0x07) || (reg_al==0x0a) || (reg_al==0x0c) || (reg_al==0x10)) {
		handle=RealHandle(reg_bx);
		if (handle>=DOS_FILES) {
			DOS_SetError(DOSERR_INVALID_HANDLE);
			return false;
		}
		if (!Files[handle]) {
			DOS_SetError(DOSERR_INVALID_HANDLE);
			return false;
		}
	} else if (reg_al<0x12) { 				/* those use a diskdrive except 0x0b */
		if (reg_al!=0x0b) {
			drive=reg_bl;if (!drive) drive = DOS_GetDefaultDrive();else drive--;
			if( !(( drive < DOS_DRIVES ) && Drives[drive]) ) {
				DOS_SetError(DOSERR_INVALID_DRIVE);
				return false;
			}
		}
	} else {
		LOG(LOG_DOSMISC,LOG_ERROR)("DOS:IOCTL Call %2X unhandled",reg_al);
		DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
		return false;
	}
	switch(reg_al) {
	case 0x00:		/* Get Device Information */
		if (Files[handle]->GetInformation() & 0x8000) {	//Check for device
			reg_dx=Files[handle]->GetInformation();
		} else {
			Bit8u hdrive=Files[handle]->GetDrive();
			if (hdrive==0xff) {
				LOG(LOG_IOCTL,LOG_NORMAL)("00:No drive set");
				hdrive=2;	// defaulting to C:
			}
			/* return drive number in lower 5 bits for block devices */
			reg_dx=(Files[handle]->GetInformation()&0xffe0)|hdrive;
		}
		reg_ax=reg_dx; //Destroyed officially
		return true;
	case 0x01:		/* Set Device Information */
		if (reg_dh != 0) {
			DOS_SetError(DOSERR_DATA_INVALID);
			return false;
		} else {
			if (Files[handle]->GetInformation() & 0x8000) {	//Check for device
				reg_al=(Bit8u)(Files[handle]->GetInformation() & 0xff);
			} else {
				DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
				return false;
			}
		}
		return true;
	case 0x02:		/* Read from Device Control Channel */
		if (Files[handle]->GetInformation() & 0xc000) {
			/* is character device with IOCTL support */
			PhysPt bufptr=PhysMake(SegValue(ds),reg_dx);
			Bit16u retcode=0;
			if (((DOS_Device*)(Files[handle]))->ReadFromControlChannel(bufptr,reg_cx,&retcode)) {
				reg_ax=retcode;
				return true;
			}
		}
		DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
		return false;
	case 0x03:		/* Write to Device Control Channel */
		if (Files[handle]->GetInformation() & 0xc000) {
			/* is character device with IOCTL support */
			PhysPt bufptr=PhysMake(SegValue(ds),reg_dx);
			Bit16u retcode=0;
			if (((DOS_Device*)(Files[handle]))->WriteToControlChannel(bufptr,reg_cx,&retcode)) {
				reg_ax=retcode;
				return true;
			}
		}
		DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
		return false;
	case 0x06:      /* Get Input Status */
		if (Files[handle]->GetInformation() & 0x8000) {		//Check for device
			reg_al=(Files[handle]->GetInformation() & 0x40) ? 0x0 : 0xff;
		} else { // FILE
			Bit32u oldlocation=0;
			Files[handle]->Seek(&oldlocation, DOS_SEEK_CUR);
			Bit32u endlocation=0;
			Files[handle]->Seek(&endlocation, DOS_SEEK_END);
			if(oldlocation < endlocation){//Still data available
				reg_al=0xff;
			} else {
				reg_al=0x0; //EOF or beyond
			}
			Files[handle]->Seek(&oldlocation, DOS_SEEK_SET); //restore filelocation
			LOG(LOG_IOCTL,LOG_NORMAL)("06:Used Get Input Status on regular file with handle %d",handle);
		}
		return true;
	case 0x07:		/* Get Output Status */
		LOG(LOG_IOCTL,LOG_NORMAL)("07:Fakes output status is ready for handle %d",handle);
		reg_al=0xff;
		return true;
	case 0x08:		/* Check if block device removable */
		/* cdrom drives and drive a&b are removable */
		if (drive < 2) reg_ax=0;
		else if (!Drives[drive]->isRemovable()) reg_ax=1;
		else {
			DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
			return false;
		}
		return true;
	case 0x09:		/* Check if block device remote */
		if (Drives[drive]->isRemote()) {
			reg_dx=0x1000;	// device is remote
			// undocumented bits always clear
		} else {
			reg_dx=0x0802;	// Open/Close supported; 32bit access supported (any use? fixes Fable installer)
			// undocumented bits from device attribute word
			// TODO Set bit 9 on drives that don't support direct I/O
		}
		reg_ax=0x300;
		return true;
	case 0x0B:		/* Set sharing retry count */
		if (reg_dx==0) {
			DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
			return false;
		}
		return true;
	case 0x0D:		/* Generic block device request */
		{
			if (Drives[drive]->isRemovable()) {
				DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
				return false;
			}
			PhysPt ptr	= SegPhys(ds)+reg_dx;
			switch (reg_cl) {
			case 0x60:		/* Get Device parameters */
				mem_writeb(ptr  ,0x03);					// special function
				mem_writeb(ptr+1,(drive>=2)?0x05:0x14);	// fixed disc(5), 1.44 floppy(14)
				mem_writew(ptr+2,drive>=2);				// nonremovable ?
				mem_writew(ptr+4,0x0000);				// num of cylinders
				mem_writeb(ptr+6,0x00);					// media type (00=other type)
				// drive parameter block following
				mem_writeb(ptr+7,drive);				// drive
				mem_writeb(ptr+8,0x00);					// unit number
				mem_writed(ptr+0x1f,0xffffffff);		// next parameter block
				break;
			case 0x46:
			case 0x66:	/* Volume label */
				{			
					char const* bufin=Drives[drive]->GetLabel();
					char buffer[11] ={' '};

					char const* find_ext=strchr(bufin,'.');
					if (find_ext) {
						Bitu size=(Bitu)(find_ext-bufin);
						if (size>8) size=8;
						memcpy(buffer,bufin,size);
						find_ext++;
						memcpy(buffer+size,find_ext,(strlen(find_ext)>3) ? 3 : strlen(find_ext)); 
					} else {
						memcpy(buffer,bufin,(strlen(bufin) > 8) ? 8 : strlen(bufin));
					}
			
					char buf2[8]={ 'F','A','T','1','6',' ',' ',' '};
					if(drive<2) buf2[4] = '2'; //FAT12 for floppies

					mem_writew(ptr+0,0);			// 0
					mem_writed(ptr+2,0x1234);		//Serial number
					MEM_BlockWrite(ptr+6,buffer,11);//volumename
					if(reg_cl == 0x66) MEM_BlockWrite(ptr+0x11, buf2,8);//filesystem
				}
				break;
			default	:	
				LOG(LOG_IOCTL,LOG_ERROR)("DOS:IOCTL Call 0D:%2X Drive %2X unhandled",reg_cl,drive);
				DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
				return false;
			}
			return true;
		}
	case 0x0E:			/* Get Logical Drive Map */
		if (Drives[drive]->isRemovable()) {
			DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
			return false;
		}
		reg_al = 0;		/* Only 1 logical drive assigned */
		return true;
	default:
		LOG(LOG_DOSMISC,LOG_ERROR)("DOS:IOCTL Call %2X unhandled",reg_al);
		DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
		break;
	}
	return false;
}