/*--------------------------------------------------------------------------
   VGA_T2-2.c - Sobre los modos palabra y doble palabra.
  --------------------------------------------------------------------------
   El programa pretende ser efectivo, esto es:lograr sus objetivos, aunque
   puede que no sea eficaz (No he optimizado nada)
  --------------------------------------------------------------------------*/
#include <conio.h>


void Set320x200NE( void );
void SetPixelNE(int x, int y, int color, int Alogico);
void SetTextMode80C( void );
void SetStartAdress( int despl );
void OutReg(int reg, int indice, int valor);
int  InReg(int reg, int indice);
void DrawBox(int x, int y, int ancho, int alto, int color);
void DrawPixels(int x, int y, int color);
void SetWordMode( int on );
void SetDWordMode( int on );
void Func1(void);
void Func2(void);
void Func3(void);
void Func4(void);
void Func5(void);
void Func6(void);
void Func7(void);
void ScanFunc(void);

unsigned Alogico=80;  /* Ancho logico de 80*4=320 pixels laterales */
unsigned x,y;
unsigned StAdress=0;  /* Desplazamiento de comienzo en la memoria */
unsigned ScanLines=1; /* N§ de lineas de escaneado */

/*+COMIENZO DE MAIN+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  Funcion principal.
  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
main()
{
 unsigned re, tecla;

/*--------------------------------------------------------------------------
   Permitimos el acceso a los indices 0-7 del CRTC
  --------------------------------------------------------------------------*/
	re=InReg(0x3d4,0x11);
	re=re&127;
	OutReg(0x3d4,0x11,re);


/*--------------------------------------------------------------------------
   Hacemos presentaciones varias.
  --------------------------------------------------------------------------*/
	while(1){
		SetTextMode80C();
		puts("\n\n\n Selecciona opcion:");
		puts("  1 - Modo byte");
		puts("  2 - Modo palabra");
		puts("  3 - Modo doble palabra");
		puts("  4 - Puntos en modo palabra");
		puts("  5 - Puntos en modo doble palabra");
		puts("  6 - Dar un nuevo valor al registro StartAdress");
		puts("  7 - Cambiar el n§ de filas de scaneado");
		puts("  0 - Salir");
		tecla=getch();
		switch(tecla){
			case '1': Func1(); getch(); break;
			case '2': Func2(); getch(); break;
			case '3': Func3(); getch(); break;
			case '4': Func4(); getch(); break;
			case '5': Func5(); getch(); break;
			case '6': Func6(); break;
			case '7': Func7(); break;
			case '0': exit(0); }
	}

/*--------------------------------------------------------------------------
   Deshabilitamos el acceso a los indices 0-7 del CRTC
  --------------------------------------------------------------------------*/
	re=InReg(0x3d4,0x11);
	re=re|128;
	OutReg(0x3d4,0x11,re);


/*--------------------------------------------------------------------------
   Restablecemos el modo de texto
  --------------------------------------------------------------------------*/
	getch();
	SetTextMode80C();
}
/*+FIN DE MAIN++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/







/*--------------------------------------------------------------------------
   DrawBox - Dibuja un cuadrado en la pantalla virtual del color escogido
  --------------------------------------------------------------------------*/
void DrawBox(int x, int y, int ancho, int alto, int color){
	unsigned cx,cy;
	for(cx=0;cx<ancho;++cx){
	for(cy=0;cy<alto;++cy){
		SetPixelNE(x+cx,y+cy,color,Alogico); }}
}

/*--------------------------------------------------------------------------
   DrawPixels - Dibuja 20 pixels contiguos
  --------------------------------------------------------------------------*/
void DrawPixels(int x, int y, int color){
	unsigned pix;
	for(pix=0;pix<20;++pix){SetPixelNE(x+pix,y,color,Alogico);getch();}
}




/*--------------------------------------------------------------------------
   SetDWordMode - Establece el modo doble palabra
  --------------------------------------------------------------------------*/
void SetDWordMode( int on )
{
 int re;
 if(on==1){ re=InReg(0x3d4,0x14);
	 re=re|64;
	 OutReg(0x3d4,0x14,re);}
 else{   re=InReg(0x3d4,0x14);
	 re=re&(255-64);
	 OutReg(0x3d4,0x14,re);}
}

/*--------------------------------------------------------------------------
   SetWordMode - Establece el modo palabra
  --------------------------------------------------------------------------*/
void SetWordMode( int on )
{
 int re;
 if(on==1){ re=InReg(0x3d4,0x17);
	 re=re&(255-64);
	 OutReg(0x3d4,0x17,re);}
 else{   re=InReg(0x3d4,0x17);
	 re=re|64;
	 OutReg(0x3d4,0x17,re);}
}

/*--------------------------------------------------------------------------
   Presentaciones - Funciones que pintan cosas
  --------------------------------------------------------------------------*/

void Func1(void){
	SetTextMode80C();
	puts(" Establecemos el modo byte.");
	puts("\n Es el modo no encadenado tipico.");
	puts("\n Pulsa una tecla");
	getch();
	Set320x200NE();
	SetStartAdress(StAdress); ScanFunc();
	for(x=0;x<16;++x){
	for(y=0;y<15;++y){
		DrawBox(x*20,y*50,20,50,y*16+x);}}
}

void Func2(void){
	SetTextMode80C();
	puts(" Establecemos ahora el modo palabra.");
	puts("\n Fijate como llena la pantalla, quedando dividida en 2.");
	puts("\n Pulsa una tecla");
	getch();
	Set320x200NE();
	SetWordMode(1);
	SetStartAdress(StAdress); ScanFunc();
	for(x=0;x<16;++x){
	for(y=0;y<15;++y){
		DrawBox(x*20,y*50,20,50,(y+1)*16+x);}}
}
void Func3(void){
	SetTextMode80C();
	puts(" Establecemos ahora el modo doble palabra.");
	puts("\n Fijate como llena la pantalla, quedando dividida en 4.");
	puts("\n Pulsa una tecla");
	getch();
	Set320x200NE();
	SetDWordMode(1);
	SetStartAdress(StAdress); ScanFunc();
	for(x=0;x<16;++x){
	for(y=0;y<15;++y){
		DrawBox(x*20,y*50,20,50,(y+1)*16+x);}}
}
void Func4(void){
	SetTextMode80C();
	puts(" Establecemos ahora el modo palabra.");
	puts(" Cada vez que pulses una tecla, se iran dibujando puntos");
	puts(" en posiciones contiguas segun el modo byte. Cuenta el");
	puts(" n§ de veces que pulsas la tecla y podras comprobar lo");
	puts(" que se cuenta en el tutorial. Se pintan 4 filas de 20");
	puts(" puntos");
	puts("\n Pulsa una tecla");
	getch();
	Set320x200NE();
	SetStartAdress(StAdress); ScanFunc();
	SetWordMode(1);
	for(y=0;y<4;++y){
		DrawPixels(0,y,(y+2)*16);}
}
void Func5(void){
	SetTextMode80C();
	puts(" Establecemos ahora el modo doble palabra.");
	puts(" Cada vez que pulses una tecla, se iran dibujando puntos");
	puts(" en posiciones contiguas segun el modo byte. Cuenta el");
	puts(" n§ de veces que pulsas la tecla y podras comprobar lo");
	puts(" que se cuenta en el tutorial. Se pintan 4 filas de 20");
	puts(" puntos");
	puts("\n Pulsa una tecla");
	getch();
	Set320x200NE();
	SetStartAdress(StAdress); ScanFunc();
	SetDWordMode(1);
	for(y=0;y<4;++y){
		DrawPixels(0,y,(y+2)*16);}
}

void Func6(void){
	SetTextMode80C();
	printf(" StartAdress=%d Introduce nuevo valor: ",StAdress);
	scanf("%d",&StAdress);
}

void Func7(void){
	SetTextMode80C();
	printf(" Lineas de scaneado=%d Introduce nuevo valor: ",ScanLines);
	scanf("%d",&ScanLines);
	ScanLines=ScanLines&15;
}

void ScanFunc(void){
	unsigned valor;
	valor=InReg(0x3d4,0x09);
	valor=(valor&0xF0)|ScanLines;
	OutReg(0x3d4,0x09, valor);
}
