?parsecommandline TRUE
?resize TRUE
?use80286
?codesize
?include "WRITE.H--"
?include "DOS.H--"
?include "FILE.H--"
?include "keycodes.h--"

?define SIZEBUF 512*24
?define NUMLOOP 5

char XPOS,YPOS;
char FDISK;
char FORMAT=FALSE;
char BUFFORM[24*4];
char SEC_SIZE,EOT,FILL_CHAR;
char USE="\nFIMAGE - создает и востанавливает образ дискеты.\n\n"
				 "Запуск: FIMAGE comand disk filename\n"
				 "где: comand = A|E|X - команды создать/востановить с форматированием/востановить\n"
				 "                      образ дискеты\n"
				 "     disk   = A|B   - буква дисковода\n"
				 "     filename       - имя файла с образом диска\n";
char BANER="\nCopyright Sheker Mishel (C)  1998.\n";
char NOTCREAT="Ошибка создания файла c образом.";
char NOMEM="Недостаточно оперативной памяти.";
char BADTYPEFLOP="Программа с этим типом дисководов не работает.";
char ERRORDISK="Ошибка работы с флоппи диском.";
char NOTOPEN="Не могу открыть файл с образом диска.";
char UCNOWNFUN="Недоступная операция.";
char NOTSUPORD="Функция не поддерживается.";
char NODISK="Не вставлена дискета.";
char NOFORMAT="Ошибка форматирования.";
char NOECVL="Формат дискеты не соответствует формату образа.";
int OFMES={#NOTCREAT,#NOMEM,#BADTYPEFLOP,#ERRORDISK,#NOTOPEN,#UCNOWNFUN,#NOTSUPORD,
           #NODISK,#NOFORMAT,#NOECVL};
int HANDL=0,BUFFER=0,NUMSEC,NUMCUL=80;
word INT1E[2];

main()
//int i;
{
	IF(@PARAMCOUNT()<3)USAGE();	//проверка комстроки
//	i=AX;
	SI=PARAMSTR(1);	//номер дисковода
	FDISK=DSBYTE[SI]&0X5F-0X41;
	IF(AL>1)USAGE();	//НЕВЕРНЫЙ НОМЕР ДИСКОВОДА
	AH=8;
	DL=AL;
	$int 0x13	//ПАРАМЕТРЫ ДИСКА
	NUMSEC=CL;
	IF(BL!=2)&&(BL!=4)error(2);	//неподдерживаемый тип дисков
	//ПРОВЕРКА НАЛИЧИЯ ДИСКА
	FOR(;;){
		AH=0x16;
		DL=FDISK;
		$int 0x13
		IF(NOTCARRYFLAG)BREAK;
		WRITESTR("\nВставте дискету в дисковод и нажмите Y или N для отмены\n");
		do{
			@BEEP();
			@BIOSREADKEY();
			IF(AH==49)EXIT(1);
		}while(AH!=21);
	}
	BUFFER=@GETMEM(SIZEBUF);	//буфер
	IF(AX==0)error(1);	//недостаточно памяти
	SI=PARAMSTR(0);		//команда
	AL=DSBYTE[SI]&0x5f;
	IF(AL=='A')ARXIV();
	ELSE IF(AL=='X')EXPAND();
	ELSE IF(AL=='E'){
		FORMAT=TRUE;
		EXPAND();
	}
	ELSE USAGE();
	FCLOSE(,HANDL);
	@FREEMEM(BUFFER);
	WRITESTR(#BANER);
}

void USAGE()
{
	WRITESTR(#USE);
	WRITESTR(#BANER);
	EXIT(1);
}

void ARXIV()
int i;
{
	DX=PARAMSTR(2);	//имя файла
	HANDL=@FCREATE(,,0);	//создать его
	IF(AX==0)error(0);
	ReadTrec(0,0);	//считать 0 дорожку
	IF(ESWORD[510]==0X0AA55){	//информация о формате дискеты
		NUMSEC=ESBYTE[24];
		NUMCUL=ESWORD[19]/2/NUMSEC;
	}
	WRITESTR("Создание образа дискеты:\n");
	INFODISK();
	FOR(i=0;i<NUMCUL;i++){	//копирование дорожек
		InfoRead(i*2);
		ReadTrec(i,0);
		WRITEFAR(,HANDL,NUMSEC*512,BUFFER);
		InfoRead(i*2+1);
		ReadTrec(i,1);
		WRITEFAR(,HANDL,NUMSEC*512,BUFFER);
	}
	FINALINFO();
}

InfoRead(int NUMS)
{
	WRITESTR("Обработано: ");
	WRITEINT(NUMS*50/NUMCUL);
	WRITESTR("%\r");
}

void INFODISK()
{
	WRITEINT(NUMCUL);
	WRITESTR(" - дорожек  ");
	WRITEINT(NUMSEC);
	WRITESTR(" - секторов\n");
}

void EXPAND()
int i;
{
	DX=PARAMSTR(2);	//имя файла с образом
	HANDL=@FOPEN(0);	//открыть на чтение
	IF(AX==0)error(4);
	READFAR(,HANDL,NUMSEC*512,BUFFER);	//считать с образа 0 дорожку
	ES=BUFFER;
	NUMSEC=ESBYTE[24];	//параметры дискеты в образе
	NUMCUL=ESWORD[19]/2/NUMSEC;
	WRITESTR("Создание дискеты с образа:\n");
	INFODISK();
	WRITELN();
	IF(FORMAT==TRUE){	//подготовка к форматированию
		GETINTVECT(#INT1E,0X1E);	//таблица параметров дискет
		ES=INT1E[2];
		BX=INT1E+3;
		SEC_SIZE=ESBYTE[BX];	//установить новый размер сектора
		ESBYTE[BX]=2;
		BX++;
		EOT=ESBYTE[BX];
		ESBYTE[BX]=NUMSEC;	//установить новое число секторов
		BX+=4;
		FILL_CHAR=ESBYTE[BX];	//новый символ заполнения
		ESBYTE[BX]=0XF6;
//		AX=0X1703;
//		DL=FDISK;
//		$INT 0X13
		AH=0X18;	//установить параметры для форматирования
		DL=FDISK;
		CH=NUMCUL-1;
		CL=NUMSEC;
		$INT 0X13
		SWITCH(char AH){
		  CASE 1: error(5);
			CASE 12: error(6);
			CASE 128: error(7);
		}
	}
	ELSE{	//если не надо фарматирование
		ReadTrec(0,0);	//считать 0 -дорожку и сравнить параметры дискеты с образом
		IF(ESBYTE[24]!=NUMSEC)||(ESBYTE[19]/2/NUMSEC!=NUMCUL)error(9);
	}
	@GETXY();
	XPOS=AL;
	YPOS=AH-1;
	GOTOXY(char XPOS,char YPOS);
	@FSEEK(char SEEK_SET,HANDL,0,0);
	FOR(i=0;i<NUMCUL;i++){
		InfoRead(i*2);
		READFAR(,HANDL,NUMSEC*512,BUFFER);
		WriteTrec(i,0);
		InfoRead(i*2+1);
		READFAR(,HANDL,NUMSEC*512,BUFFER);
		WriteTrec(i,1);
	}
	FINALINFO();
	IF(FORMAT==TRUE){	//востановить предыдущие параметры таблицы
		ES=INT1E[2];
		BX=INT1E+3;
		ESBYTE[BX]=SEC_SIZE;
		BX++;
		ESBYTE[BX]=EOT;
		BX+=4;
		ESBYTE[BX]=FILL_CHAR;
	}
}

void FINALINFO()
{
	WRITESTR("Обработано: 100%\n");
}

void error(int ERNUM)
{
	WRITELN();
	WRITESTR(OFMES[ERNUM]);
	WRITELN();
	EXIT(ERNUM+2);
}

ReadTrec(int cul,head)
int loops;
{
	FOR(loops=0;loops<NUMLOOP;loops++){
		CH=cul;
		CL=1;
		DH=head;
		DL=FDISK;
		ES=BUFFER;
		BX=0;
		AH=2;
		AL=NUMSEC;
		$INT 0X13
		IF(NOTCARRYFLAG)BREAK;
	}
	IF(loops==NUMLOOP)error(3);
}

WriteTrec(int cul,head)
int loops;
{
	IF(FORMAT==TRUE){
		WRITESTR("\nОперация: форматирование");
		ES=DS;
		FOR(DI=#BUFFORM,loops=1;loops<=NUMSEC;loops++){	//создать образ форматируемой дорожки
			AL=cul;
			$STOSB
			AL=head;
			$STOSB
			AL=loops;
			$STOSB
			AL=2;
			$STOSB
		}
		FOR(loops=0;loops<NUMLOOP;loops++){
			CH=cul;
//			CL=1;
			DH=head;
			DL=FDISK;
			BX=#BUFFORM;
			AH=5;
			AL=NUMSEC;
			$INT 0X13
			IF(NOTCARRYFLAG)BREAK;
		}
		IF(loops==NUMLOOP)error(8);
		GOTOXY(char XPOS+10,char YPOS+1);
		WRITESTR("запись        ");
		GOTOXY(char XPOS,char YPOS);
	}
	FOR(loops=0;loops<NUMLOOP;loops++){
		CH=cul;
		CL=1;
		DH=head;
		DL=FDISK;
		ES=BUFFER;
		BX=0;
		AH=3;
		AL=NUMSEC;
		$INT 0X13
		IF(NOTCARRYFLAG)BREAK;
	}
	IF(loops==NUMLOOP)error(3);
}
