#include    <graph.h>
#include    "vga_new.h"

/**
*.Name    Set360x480Mode
*
*.Title   Установка режима 360х480 пикселов, 256 цветов.
*
*.Proto   void Set360x480Mode( void )
*
*.Params  Не используются.
*
*.Return  Не используетя.
*
*.Sample  e256hres.c
**/

void    Set360x480Mode( void ) {

	_asm  {

		// устанавливаем режим 12h, чтобы очистить видеопамять
		mov     ax,12h
		int     10h

		// устанавливаем стандартный режим 13h (320x200 пикселов, 256 цветов)
		mov     ax,0013h
		int     10h

		// перепрограммируем регистр определения структуры памяти:
		// запрещаем адресацию к разным слоям памяти в зависимости от
		// кратности адреса памяти четырем (бит D4 chain4)
		mov   dx,SC_INDEX
		mov   ax,0604h
		out   dx,ax

		// производим синхронный сброс и остановку синхронизатора
		mov   ax,0100h
		out   dx,ax

		// адресуемся к регистру определения различных режимов работы
		mov   dx,MOR

		// устанавливаем частоту кадров 60Кц
		mov   al,0e7h
		out   dx,al

		// запускаем синхронизатор
		mov   dx,SC_INDEX
		mov   ax,0300h
		out   dx,ax


		// выбираем регистр режима работы графического контроллера
		mov     dx,GC_INDEX
		mov     al,MDR
		out     dx,al

		// считываем его значение
		inc     dx
		in      al,dx

		// выключаем доступ по четным адресам к четным слоям, а по
		// нечетным адресам к нечетным слоям
		and     al,11101111b
		out     dx,al

		// выбираем регистр смешанного назначения графического контроллера
		dec     dx
		mov     al,MIR
		out     dx,al

		// считываем его значение
		inc     dx
		in      al,dx

		// сбрасываем бит управляющий сцеплением четных и нечетных слоев
		and     al,11111101b
		out     dx,al


		// выбираем регистр конца обратного вертикального хода луча
		mov   dx,3d4h
		mov   al,11h
		out   dx,al

		// снимаем защиту от записи с регистров контроллера ЭЛТ,
		// имеющих индексы от 0 до 7
		inc   dx
		in    al,dx
		and   al,7fh
		out   dx,al

		dec   dx

		// программируем регистры контроллера ЭЛТ, втом числе
		// регистры, определяющие временные параметры режима

		// устанавливаем регистр общей длины линии горизонтальной
		// развертки
		mov   ax,06b00h
		out   dx,ax

		// устанавливаем регистр длины отображаемой части
		// горизонтальной развертки
		mov   ax,05901h
		out   dx,ax

		// устанавливаем регистр начала импульса гашения луча
		// горизонтальной развертки
		mov   ax,05a02h
		out   dx,ax

		// устанавливаем регистр конца импульса гашения луча
		// горизонтальной развертки
		mov   ax,08e03h
		out   dx,ax

		// устанавливаем регистр начала импульса горизонтального
		// обратного хода луча
		mov   ax,05e04h
		out   dx,ax

		// устанавливаем регистр конца импульса горизонтального
		// обратного хода луча
		mov   ax,08a05h
		out   dx,ax

		// устанавливаем регистр числа горизонтальных линий
		// растра
		mov   ax,0d06h
		out   dx,ax

		// устанавливаем дополнительный регистр
		mov   ax,03e07h
		out   dx,ax

		// устанавливаем регистр высоты символов текста
		mov   ax,04009h
		out   dx,ax

		// устанавливаем регистр начала обратного
		// вертикального хода луча
		mov   ax,0ea10h
		out   dx,ax

		// устанавливаем регистр конца обратного
		// вертикального хода луча
		mov   ax,0ac11h
		out   dx,ax

		// устанавливаем регистр начала гашения вертикальной
		// развертки
		mov   ax,0df12h
		out   dx,ax

		// устанавливаем регистр логической ширины экрана
		mov   ax,02d13h
		out   dx,ax

		// устанавливаем регистр положения подчеркивания символа
		mov   ax,014h
		out   dx,ax

		// устанавливаем регистр начала импульса гашения
		// вертикальной развертки
		mov   ax,0e715h
		out   dx,ax

		// устанавливаем регистр конца импульса гашения
		// вертикальной развертки
		mov   ax,0616h
		out   dx,ax

		// устанавливаем регистр управления режимом
		mov   ax,0e317h
		out   dx,ax
	}
}


/**
*.Name    WritePixel_H
*
*.Title   Отображение пиксела.
*
*.Descr   Функция отображает на экране пиксел в заданных координатах,
*         определенного цвета.
*
*.Proto   void WritePixel_H(unsigned x, unsigned y, unsigned char color)
*
*.Params  x - x-координата пиксела (0-319),
*
*         y - y-координата пиксела (0-399),
*
*         color - цвет пиксела (0-255).
*
*.Return  Не используетя.
*
*.Sample  e256hres.c
**/

void  WritePixel_H(unsigned x, unsigned y, unsigned char color) {

	_asm  {

		push    di

		mov     cx,x
		mov     dx,y
		mov     bl,color


		mov     ax,VGA_SEGMENT
		mov     es,ax

		mov     ax,( SCREEN_WIDTH_H / 4 )
		mul     dx

		push    cx

		shr     cx,1
		shr     cx,1

		add     ax,cx
		mov     di,ax

		pop     cx

		and     cl,3
		mov     ah,1
		shl     ah,cl

		mov     dx,SC_INDEX
		mov     al,CPWER
		out     dx,ax

		mov     es:[di],bl

		pop     di
	}
}


/**
*.Name    ReadPixel_H
*
*.Title   Определение цвета пиксела.
*
*.Descr   Функция возвращает значение байта видеопамяти, определяющего пиксел
*         с заданными координатами.
*
*.Proto   unsigned char ReadPixel_H(unsigned x, unsigned y, unsigned char color)
*
*.Params  x - x-координата пиксела (0-319),
*
*         y - y-координата пиксела (0-399).
*
*.Return  цвет пиксела (0-255).
*
*.Sample  e256hres.c
**/

unsigned char   ReadPixel_H( unsigned x, unsigned y ) {

	unsigned char  color;

	_asm  {

		push    si

		mov     cx,x
		mov     dx,y

		mov     ax,VGA_SEGMENT
		mov     es,ax

		mov     ax,( SCREEN_WIDTH_H / 4 )
		mul     dx

		push    cx

		shr     cx,1
		shr     cx,1

		add     ax,cx
		mov     si,ax

		pop     ax

		and     al,3
		mov     ah,al

		mov     dx,GC_INDEX
		mov     al,RPSR
		out     dx,ax

		mov     al,es:[si]
		mov     color,al

		pop     si
	}

	return( color );
}


/**
*.Name    Full_Scr_H
*
*.Title   Закрашивает экран заданным цветом.
*
*.Proto   void Full_Scr_H( unsigned char color )
*
*.Params  color - цвет экрана (0-255).
*
*.Return  Не используетя.
*
*.Sample  e256hres.c
**/

void Full_Scr_H( unsigned char color ) {

	_asm {

		push    di

		;разрешаем запись данных во все четыре цветовых слоя

		mov     dx,SC_INDEX
		mov     al,CPWER
		out     dx,al

		mov     al,0fh
		out     dx,al


		mov     ax,VGA_SEGMENT
		mov     es,ax

		xor     di,di
		mov     al,color

		mov     cx,43200
		cld
		rep     stosb

		pop     di
	}
}


void main( void ){

	unsigned i;
	char ch = 13;

	struct videoconfig vc;

	// заполняем поля структуры vc

	printf("\n   (C) Frolov G.V., 1992\n\n");
	_getvideoconfig( &vc );

	// завершаем программу если нет VGA адаптера

	if(vc.adapter != _VGA) {
		printf("Для выполнения программы нобходим адаптер VGA\n");
		exit(0);
	}


	// устанавливаем режим 360х480 пикселов, 256 цветов

	Set360x480Mode();

	// загружаем регистры ЦАП VGA

	LoadVGA256();

	for(i = 0; i < 480; i++)
		WritePixel_H(180, (unsigned) i, (unsigned char) (i % 256) );

	for(i = 0; i < 360; i++)
		WritePixel_H((unsigned) i, 240, (unsigned char) (i % 256) );

	ch = getch();
	if( ch == 27 ) exit(1);

	for(i = 0; i < 360; i++)
		WritePixel_H((unsigned) i, (unsigned) i, (unsigned char) (i % 256) );

	ch = getch();

	for(i = 0; ((i < 256) && (ch != 27)); i++) {
		Full_Scr_H( (unsigned char) i );
		ch = getch();
	}


	// возвращаемся в текстовый режим

	_setvideomode(_DEFAULTMODE);

	printf("Привет всем!!!\n");
}

