TITLE	pcfv.asm - deal with CGA/EGA displays
;; C Durland	Public Domain
;; Routines:
;;   fv_init()
;;   putline(row,buf,attr) int row,attr; char *buf;
;;   void t_move(row,col) int row, col;
;;   void t_eeol()
;; Use this file with pcio.c and FASTVIDEO.
;; Equivalent C routines are in pcfv.c.

	INCLUDE	DOSl.MAC

	DSEG
tcolor	DW 7		; text color default
mcolor	DW 96		; modeline color default
vseg	DW 0B800H	; segment where the video ram starts
p_ncol	DB 0		; screen hardware columns per row
DS40	DW 40H
zcolor	DB 0		; color the BIOS is using

EXTRN t_ncol:WORD, t_nrow:WORD
PUBLIC tcolor, mcolor
	ENDDS

	PSEG				; begin program segment

;
; putline(row,buf,attr) int row,attr; char *buf;
;
	BEGIN putline
	PUSH  BP
	MOV   BP,SP

	push DS
	push ES
	push DI
	push SI
	push BX
	push CX

		; calc screen address
	mov AX,[BP+04H]		; row
	mul p_ncol
	shl AX,1
;mov BX,AX
;mov CL,5
;shl BX,CL	; row * 32
;mov CL,7
;shl AX,CL	; row * 128
;add AX,BX	; row * 128 + row * 32 = row * 160

	mov ES,vseg	; screen segment
	mov DI,AX	; offset of row

	MOV  AH,[BP+0AH]	; attr
	mov CX,t_ncol

	mov  SI,[BP+06H]	; buf address
	mov  DS,[BP+08H]

	CLD
pl10:
	LODSB		; AL = *buf++
	STOSW		; *screen++ = character, *screen++ = attr
	LOOP pl10

	pop CX
	pop BX
	pop SI
	pop DI
	pop ES
	pop DS
	POP BP
	RET
putline	ENDP


;
; fv_init()	; initialize fast video stuff
;   Find the video segment.
;   Find and set the column count.
;   Find and set the row count if on EGA/VGA.
;   Find the video attribute the BIOS is using for modeline writes.

	BEGIN fv_init

	push ES
	push BX
	push CX
	push DX

	  ; find the video segment
	mov AH,0FH
	int 10H
	cmp AL,7	; is it monochrome?
	jNE fv10	; no, its color so vseg is OK.
	mov vseg,0B000H
fv10:
	  ; get the column count
	xor AX,AX
	mov ES,DS40
	mov AL,ES:4AH		; 40:4A has number of columns
	mov p_ncol,AL		; for hardware
	mov t_ncol,AX		; for ME
	  ; detect EGA/VGA
	mov AX,1200H
	mov BX,10H
	mov CX,-1
	int 10H
	cmp CX,-1
	jE notEGA	; if CX didn't change it ain't EGA
	xor AX,AX
	mov ES,DS40
	mov AL,ES:84H	; 40:84 has number of rows-1
	mov t_nrow,AX
notEGA:
    ;; now figure out the attribute that the BIOS is using.
	  ;; move cursor to (0,0)
	mov  AH,2
	mov  BH,0
	xor  DX,DX
	int  10H
	  ;; now write a blank with the current attribute
	mov  AH,6
	mov  DL,' '
	int  21H
	  ;; read the attribute and save it
	mov  AH,2	;; move cursor to (0,0)
	mov  BH,0
	xor  DX,DX
	int  10H
	mov  AH,8H	;; read character/attribute
	int  10H
	mov  zcolor,AH

	pop DX
	pop CX
	pop BX
	pop ES
	RET
fv_init	ENDP

;
; void t_move(row,col) int row, col;	/* move cursor to (row,col) */
; (row,col) are zero relative as is the PC.
;
	BEGIN t_move 
	PUSH  BP
	MOV   BP,SP

	push BX
	push DX

	mov DH,[BP+04H]		; row
	mov DL,[BP+06H]		; col
	mov BH,0		; page 0
	mov AH,2
	int 10h

	pop DX
	pop BX
	pop BP
	ret
t_move	ENDP

;
; void t_eeol()		/* erase from cursor to end of line */
;
	BEGIN t_eeol

	push ES
	push DI
	push BX
	push CX
	push DX

	mov BH,0		; page 0
	mov AH,3
	int 10h			; DH has cursor row, DL has column

	mov AL,p_ncol
	mul DH			; row * columns per line
	shl AX,1		; 2 bytes per character
	xor DH,DH
	add AX,DX		; add in offset from start of line
	add AX,DX

	mov CX,t_ncol
	sub CX,DX		; columns to clear
	jLE eeol10		; bail out if already past t_ncol

	mov ES,vseg		; screen segment
	mov DI,AX		; offset of row

;	mov AX,ES:[DI]		; grab the attr at the cursor
;	mov AH,byte ptr tcolor	; fill with the text color
	mov AH,zcolor
	mov AL,20H		; a blank

	CLD
	rep stosw

eeol10:
	pop DX
	pop CX
	pop BX
	pop DI
	pop ES
	ret
t_eeol	ENDP

	ENDPS				; end the program segment
	END				; end the source file
