/*--------------------------------------------------------------------------*/
/*	Program name: 5_2_10.C                                              */
/*	Compile mode: Small                                                 */
/*	Image   file: 5_2_10.EXE                                            */
/*	Note        : Slot Lock protection program.                         */
/*                    For .COM file. ( New version )                        */
/*		      You can rename this program to SLOTLOCK.EXE.          */
/*		      All rights reserved !!                                */
/*--------------------------------------------------------------------------*/

#include	<stdio.h>
#include	<dos.h>
#include	<fcntl.h>
#include	<io.h>
#include	<alloc.h>

struct	DISK_PARM {	char	SRT;
			char	HLT;
			char	WAIT_TIME;
			char	N;		/* may  be set to 2	*/
			char	EOT;		/* must be set to 9	*/
			char	GAP;		/* must be set to 2AH	*/
			char	DTL;		/* may  be set to FFH	*/
			char	GAP3;		/* must be set to 50H	*/
			char	FILL;		/* may  be set to F6H	*/
			char	SETTLE;
			char	START_TIME;
		  }	far	*disk_parm,disk_parm_buffer;
unsigned	char	Head,Drive,Track,Sector,N;
unsigned	char	format_parm[20][4];
unsigned	char	*sector_data;
unsigned	char	slot_data[5];
unsigned	int	slot_ptr;
signed		int	fh,fh1,fh2;
signed		char	prot_code_file[]="SLOTLOCK.DAT";

/*--------------------------------- UTILITY --------------------------------*/

save_disk_parm()
{	char	far	*p,*q,i;

	p=(char far *)disk_parm;
	q=(char *)&disk_parm_buffer;
	for(i=0;i<11;i++)	*q=*p;
}

restore_disk_parm()
{	char	far	*p,*q,i;

	p=(char far *)disk_parm;
	q=(char *)&disk_parm_buffer;
	for(i=0;i<11;i++)	*p=*q;
}

show_disk_error_msg(int	ah)
{	printf("ERROR_CODE:%02X   ",ah);
	switch(ah)
	{	case	0x01:	printf("BAD_CMD\n\r");		break;
		case	0x02:	printf("BAD_ADDR_MARK\n\r");	break;
		case	0x03:	printf("WRITE_PROTECT\n\r");	break;
		case	0x04:	printf("RECORD_NOT_FND\n\r");	break;
		case	0x06:	printf("MEDIA_CHANGE\n\r");	break;
		case	0x08:	printf("BAD_DMA\n\r");		break;
		case	0x09:	printf("DMA_BOUNDARY\n\r");	break;
		case	0x10:	printf("BAD_CRC\n\r");		break;
		case	0x20:	printf("BAD_NEC\n\r");		break;
		case	0x40:	printf("BAD_SEEK\n\r");		break;
		case	0x80:	printf("TIME_OUT\n\r");		break;
	}
}

show_disk_error()
{	unsigned	char	ah;

	_AH=1;
	geninterrupt(0x13);
	ah=_AH;
	show_disk_error_msg(ah);
}

disk_reset()
{	_AX=0;
	geninterrupt(0x13);
}

/*--------------------------------- FORMAT ---------------------------------*/

format_reset()
{	int	i;

	for(i=0;i<5;i++)
	{	_DH=0;
		_DL=Drive;
		_AX=0x1702;
		geninterrupt(0x13);
		if ((_FLAGS&1)==0) return(0);
	}
	return(1);
}

format_track()
{	int	es;

	es=_ES;
	_ES=FP_SEG(format_parm);
	_BX=FP_OFF(format_parm);
	_CH=Track;
	_CL=Sector;
	_DH=Head;
	_DL=Drive;
	_AX=0x0501;
	geninterrupt(0x13);
	_ES=es;
	if ((_FLAGS&1)==0)	return(0);
	else			return(1);
}

set_format_parm()
{	int	i;

	for(i=0;i<9;i++)
	{	format_parm[i][0]=Track;
		format_parm[i][1]=Head;
		format_parm[i][2]=i+1;
		format_parm[i][3]=N;
	}
}

format()
{	printf("formatting...");
	set_format_parm();
	disk_reset();
	if (format_reset())
	{	printf("error!\n\r");
		show_disk_error();
		return(1);
	}
	if (format_track())
	{	printf("error!\n\r");
		show_disk_error();
		return(1);
	}
	printf("done!\n\r");
	return(0);
}

/*--------------------------------- CHECK ----------------------------------*/

read_sector()
{	int	es;

	disk_parm->N=6;
	es=_ES;
	_ES=FP_SEG(sector_data);
	_BX=FP_OFF(sector_data);
	_CH=Track;
	_CL=Sector;
	_DH=Head;
	_DL=Drive;
	_AX=0x0201;
	geninterrupt(0x13);
	_ES=es;
	disk_parm->N=2;
	if ((_FLAGS&1)==0)	return(0);
	else			return(1);
}

check()
{	int	i,j;
	unsigned	char	ah;
	unsigned	char	*temp;

	printf("checking...");
	disk_reset();
	if ((temp=sector_data=(unsigned char *)malloc(8192*2))==NULL)
	{	printf("memory allocation error!\n\r");
		return(1);
	}
	_AX=FP_SEG(sector_data)*16;
	_AX+=FP_OFF(sector_data);
	_AX+=8192;
	if (_FLAGS&1)	sector_data+=8192;
	for(i=0;i<100;i++)
	{	for(j=0;j<8192;j++)	sector_data[j]=0;
		for(j=0;j<3;j++)
		{	if (read_sector())
			{	_AH=1;
				geninterrupt(0x13);
				ah=_AH;
				if (ah==0x10)	break;
			}
		}
		if (j==3)
		{	printf("read_sector error!\n\r");
			show_disk_error_msg(ah);
			return(1);
		}

		if (i==0)
		{	for(slot_ptr=0x1700;slot_ptr<8192;slot_ptr++)
				if (sector_data[slot_ptr]!=0x4E) break;
			if ((slot_ptr==8192)||(slot_ptr==0x1700))
			{	printf("sector_data error!\n\r");
				return(1);
			}
			slot_ptr--;
			for(j=0;j<5;j++) slot_data[j]=sector_data[slot_ptr+j];
		}
		else
		{	for(j=0;j<5;j++)
				if (sector_data[slot_ptr+j]!=slot_data[j])
					break;
			if (j<5)
			{	printf("slot not stable!\n\r");
				return(1);
			}
		}
	}
	free(temp);
	printf("done!\n\r");
	return(0);
}

/*---------------------------------- MERGE ---------------------------------*/

merge()
{	unsigned	head[256],*prot_code;
	long		len,prot_code_len;
	int		i;

	printf("Merging...");

	/*-------------------------------------*/
	/* Read protection code to prot_code[] */
	/*-------------------------------------*/

	prot_code_len=lseek(fh,0,SEEK_END);
	lseek(fh,0,SEEK_SET);
	if ((prot_code=(unsigned int *)malloc(prot_code_len))==NULL)
	{	printf("memory allocation error!\n\r");
		return(1);
	}
	_read(fh,prot_code,prot_code_len);
	_close(fh);

	/*-------------------------------------*/
	/* Clear the head component            */
	/*-------------------------------------*/

	for(i=0;i<256;i++)	head[i]=0;

	/*-------------------------------------*/
	/* Calculate the protected file length */
	/*   and make the head component of the*/
	/*   output file.                      */
	/*-------------------------------------*/

	head[0]=0x5A4D;
	head[4]=0x20;
	head[6]=0xFFFF;
	head[12]=0x22;
	len=lseek(fh1,0,SEEK_END)+512;
	lseek(fh1,0,SEEK_SET);
	if (len%16!=0)	len=len+16-len%16;
	head[2]=(len+prot_code_len)/512;
	head[1]=(len+prot_code_len)%512;
	if (head[1]!=0)	head[2]++;
	head[5]=(65535-(len-512)-prot_code_len)/16+1;

	prot_code[2]=0x100;
	prot_code[3]=-0x10;
	prot_code[4]=slot_ptr;
	prot_code[5]=((unsigned int *)slot_data)[0];
	prot_code[6]=((unsigned int *)slot_data)[1];
	head[10]=0x100;
	head[11]=len/16-head[4]-0x10;

	/*-------------------------------------*/
	/* Copy and Merge                      */
	/*-------------------------------------*/

	_write(fh2,head,512);
	while((len-=512)>512)
	{	_read(fh1,head,512);
		_write(fh2,head,512);
	}
	_read(fh1,head,len);
	_write(fh2,head,len);
	_write(fh2,prot_code,prot_code_len);

	_close(fh1);
	_close(fh2);
	free(prot_code);
	printf("done!\n\r");
	return(0);
}

/*---------------------------------- MAIN ----------------------------------*/

init()
{	disk_parm=MK_FP(0,0x0522);
	save_disk_parm();
	disk_parm->N=2;
	disk_parm->EOT=9;
	disk_parm->GAP=0x2A;
	disk_parm->GAP3=0x50;
	Track=0x28;
	Head=0;
	Drive=0;
	Sector=1;
	N=6;
}

quit()
{	restore_disk_parm();
}

parameter_check()
{	extern	int	_argc;
	extern	char	**_argv;

	if (_argc>3)
	{	printf("Too many parameters.\n\r");
		return(1);
	}
	if (_argc==1)
	{	printf("Usage: SLOTLOCK [path]source.com [path]target.exe\n\r");
		return(1);
	}
	if (_argc<3)
	{	printf("Too few parameters.\n\r");
		return(1);
	}
	printf("Press any key to continue...\n\r");
	getch();
	if ((fh=_open(prot_code_file,O_RDONLY))==-1)
	{	printf("Can not open %s.\n\r",prot_code_file);
		return(1);
	}
	if ((fh1=_open(_argv[1],O_RDONLY))==-1)
	{	printf("Can not open %s.\n\r",_argv[1]);
		return(1);
	}
	if ((fh2=_creat(_argv[2],FA_ARCH))==-1)
	{	printf("Can not creat %s.\n\r",_argv[2]);
		return(1);
	}
	return(0);
}

slotlock()
{	char	ch;

	if (parameter_check())	return(1);
	if (format())		return(1);
	if (check())		return(1);
	if (merge())		return(1);
	printf("\n\n\rAll done!\n\r");
}

main()
{	init();
	slotlock();
	quit();
}
