
;---------------------------------------------------------------------------
; VGA_ASM1.asm
;---------------------------------------------------------------------------
; Aqui estan las rutinas en ensamblador que utiliza el programa VGA_TUT1.c
; Las he escrito especificamente para este primer tutorial, por lo que no
; tienen gran generalidad. Sin embargo son utiles para comenzar a ver como
; funcionan los modos no encadenados. En proximos tutoriales daremos rutinas
; mas generales y mejor disenyadas, tratando de optimizarlas al maximo.
; Estas son buenas para el proposito de este primer tutorial: mostrar nuevas
; posibilidades.
;---------------------------------------------------------------------------



; Algunas direcciones de uso frecuente
DIR_SEQ         equ 03c4h       ; Indice del controlador de secuencia
DIR_CRTC        equ 03d4h       ; Indice del controlador CRT
VIDEO_S         equ 0A000h      ; Segmento de video


		.model small

		.code
		public    _Set320x200NE,_SetPixelNE,_SetStartAdress
		public    _SetTextMode80C,_OutReg,_InReg

;---------------------------------------------------------------------------
; SetTextMode80C - Retorna al modo de texto. Establece el modo 0x03
;---------------------------------------------------------------------------
_SetTextMode80C proc
		 mov   ax,0003h     ;No hace mas que pedir al BIOS
		 int   10h          ;que cambie al modo 3, texto a color
		 ret
_SetTextMode80C endp

;---------------------------------------------------------------------------
; Set320x200NE - Establece el modo 320x200 no encadenado
;---------------------------------------------------------------------------
_Set320x200NE  proc

		push  bp
		push  si
		push  di

		mov   ax,0013h          ; Lo primero que haremos sera pedir
		int   10h               ; al BIOS que nos ponga el modo 13h

		mov   dx,DIR_SEQ        ; Acontinuacion ponemos a 0 el bit 3
		mov   ax,0604h          ; del indice 4 del secuenciador
		out   dx,ax

		mov   dx,DIR_SEQ        ; Seleccionamos los cuatro bloques
		mov   ax,0f02h          ; de memoria a la vez. Haciendo esto,
		out   dx,ax             ; cada vez que escribamos algo en una

		cld                     ; direccion del segmento de video,
		mov   ax,VIDEO_S        ; se escribira en los cuatro planos
		mov   es,ax             ; a la vez. Lo hacemos ahora porque
		sub   di,di             ; queremos borrar TODA la memoria de
		sub   ax,ax             ; video.
		mov   cx, 08000h
		rep   stosw


		mov   dx,DIR_CRTC       ; Quitamos el word mode
		mov   ax,0e317h         ; Ponemos a 1 el bit 6 del indice 17
		out   dx,ax             ; de la CRTC

		mov   dx,DIR_CRTC       ; Quitamos el double word mode
		mov   ax,00014h         ; Ponemos a 0 el bit 6 del indice 14
		out   dx,ax             ; de la CRTC

		pop   di
		pop   si
		pop   bp
		ret

_Set320x200NE  endp


;---------------------------------------------------------------------------
; params - Es una estructura de como se pasa la pila en lenguaje C
;          Si no te interesa como lo hace, prescinde completamente de ella.
;          Los parametros que se pasan a cada funcion son p1,p2,p3,etc.
;---------------------------------------------------------------------------
params          struc
		dw    2 dup (?)
   p1           dw    ?
   p2           dw    ?
   p3           dw    ?
   p4           dw    ?
params          ends


;---------------------------------------------------------------------------
; SetPixelNE - Dibuja un punto en modos no encadenados
;               Parametros: p1=x,p2=y,p3=color,p4=Alogico
;---------------------------------------------------------------------------
_SetPixelNE    proc

		push  bp
		mov   bp,sp

		mov   ax, [bp+p4]       ; En primer lugar hallamos el
		mul   [bp+p2]           ; desplazamiento.
		mov   bx,[bp+p1]
		shr   bx,1
		shr   bx,1
		add   bx,ax

		mov   ax,VIDEO_S        ; Ponemos en es el valor del
		mov   es,ax             ; segmento de video.

		mov   cl,byte ptr [bp+p1] ; El bloque: x%4
		and   cl,011b

		mov   al,02h            ; Seleccionamos el bloque
		mov   ah,01h
		shl   ah,cl
		mov   dx,DIR_SEQ
		out   dx, ax

		mov   al,byte ptr [bp+p3] ; Dibujamos el punto con 'color'
		mov   es:[bx],al

		pop   bp
		ret

_SetPixelNE     endp


;---------------------------------------------------------------------------
; OutReg  -  Funcion C para hacer un out
;            Parametros: p1=registro p2=indice p3=valor
;---------------------------------------------------------------------------
_OutReg         proc

		push  bp
		mov   bp,sp

		mov   dx, [bp+p1]
		mov   al, byte ptr [bp+p2]
		mov   ah, byte ptr [bp+p3]
		out   dx, ax

		pop   bp
		ret

_OutReg         endp


;---------------------------------------------------------------------------
; InReg   -  Funcion C para hacer un in
;            Parametros: p1=registro p2=indice
;---------------------------------------------------------------------------
_InReg          proc

		push  bp
		mov   bp,sp

		xor   ax, ax
		mov   dx, [bp+p1]
		mov   al, byte ptr [bp+p2]
		out   dx, al
		inc   dx
		in    al, dx

		pop   bp
		ret

_InReg          endp



;---------------------------------------------------------------------------
; SetStartAdress - Establece el desplazamiento origen de la pantalla
;                  Parametros: p1=desplazamiento
;---------------------------------------------------------------------------
_SetStartAdress proc
		push  bp
		mov bp, sp

		mov   cx,[bp+p1]

		mov   dx,DIR_CRTC       ; Situa los bytes alto y bajo
		mov   al, 0ch           ; del desplazamiento, en los
		mov   ah, ch            ; registros adecuados.
		out   dx, ax
		mov   al, 0dh
		mov   ah, cl
		out   dx, ax

		pop   bp
		ret
_SetStartAdress endp


end
