; --------------------------------------------------------------------- ;
; wind.asm			Citadel 				;
;			fast stuff for screen i/o			;
; --------------------------------------------------------------------- ;

ideal
model large, c

; --------------------------------------------------------------------- ;
;				Contents				;
; --------------------------------------------------------------------- ;
;  cls_fast		Clears the screen				;
;  physPosition		Positions the cursor				;
;  clearline		Clears a line on the screen			;
;  physReadpos		Reads the cursor position			;
;  readcursorsize	Reads the cursor size				;
;  fastcpy		Copies memory quickly				;
;  directstring		Writes string to screen				;
;  directchar		Writes character to screen			;
;  fastsetw		Like memset() but uses words, not chars		;
;  statDisp		Displsy for F4 screen				;
;  gmode		Returns current video mode			;
;  curshalf		Sets the cursor to be a half-block		;
;  curson		Turns on display of the cursor			;
;  cursoff		Turns off display of the cursor			;
;  putatrb		Sets attribute of an area of the screen		;
;  putmsgnc		Displays on the screen without changing color	;
;  critical_error	Tells DOS what to do				;
; --------------------------------------------------------------------- ;

public cls_fast, physPosition, physReadpos, fastcpy, clearline, directchar
public directstring, fastsetw, statDisp, gmode, curson, cursoff
public curshalf, critical_error
; public putatrb, putmsgnc

dataseg
extrn	dgLogiScreen: word, physScreen: word, conRows: byte, conCols: byte
extrn	conMode: word, dgLogiRow: byte, dgLogiCol: byte

codeseg

proc cls_fast uses di, attr:byte
	mov di, [dgLogiScreen]
	mov es, [dgLogiScreen+2]

	mov al, [conCols]
	mov bl, [conRows]
	inc bl
	mul bl

	mov cx, ax

	xor ax, ax
	mov ah, [attr]

	rep stosw
	ret
endp

proc physPosition row:byte, col:byte
	mov ah, 2
	mov dh, [row]
	mov dl, [col]
	mov bh, 0
	int 10h
	ret
endp

proc clearline row:byte, attr:byte
	mov ah, 2
	xor dx, dx
	mov dh, [row]
	mov bh, 0
	int 10h

	mov ax, 0920h		; 09h - write; 20h - space
	mov bl, [attr]
	xor cx, cx
	mov cl, [conCols]
	int 10h 		; bh should still be 0

	ret
endp

proc physReadpos row:dword, col:dword
	mov ah, 3
	mov bh, 0
	int 10h

	mov es, [word ptr row+2]
	mov bx, [word ptr row]
	mov [es:bx], dh

	mov es, [word ptr col+2]
	mov bx, [word ptr col]
	mov [es:bx], dl

	ret
endp

proc readcursorsize cstart:dword, cend:word
	mov ah, 3
	mov bh, 0
	int 10h

	mov es, [word ptr cstart+2]
	mov bx, [word ptr cstart]
	mov [es:bx], ch

	mov es, [word ptr cend+2]
	mov bx, [word ptr cend]
	mov [es:bx], cl

	ret
endp

proc fastcpy uses ds si di, dest:dword, src:dword, len:word
	mov ds, [word ptr src+2]
	mov si, [word ptr src]

	mov es, [word ptr dest+2]
	mov di, [word ptr dest]

	mov cx, [len]
	shr cx, 1

	rep movsw

	jnc done_fastcpy

	movsb

done_fastcpy:
	ret
endp

proc directstring uses ds si di, row:word, str:dword, attr:byte, phys:byte
	cmp [phys], 0
	je ds_logi

	mov di, [physScreen]
	mov es, [physScreen+2]
	jmp short ds_out

ds_logi:
	mov di, [dgLogiScreen]
	mov es, [dgLogiScreen+2]

ds_out:
	mov al, [conCols]
	mul [byte ptr row]	; was [row]
	shl ax, 1		; where on screen...

	add di, ax

	mov ds, [word ptr str+2]
	mov si, [word ptr str]

	mov ah, [attr]

ds_loop:
	lodsb
	or al, al
	jz ds_done
	stosw
	jmp short ds_loop

ds_done:
	ret
endp


proc directchar uses di, och:byte, attr:byte, phys:byte
	cmp [phys], 0
	je dc_logi

	mov di, [physScreen]
	mov es, [physScreen+2]
	jmp short dc_out

dc_logi:
	mov di, [dgLogiScreen]
	mov es, [dgLogiScreen+2]

dc_out:
	mov dl, [dgLogiCol]
	mov dh, [dgLogiRow]
	mov cx, dx

	mov al, [conCols]
	mul dh
	mov dh, 0
	shl ax, 1
	shl dx, 1

	add di, ax
	add di, dx

	mov al, [och]
	mov ah, [attr]

	stosw

	inc cx
        cmp cl, [conCols]
	je dc_scroll

;	mov [savePos], cx

;------------------
;	mov ah, 2
;	mov dx, cx
;	mov bh, 0
;	int 10h
;------------------cursor positioning now done by caller

	xor ax, ax
	ret

dc_scroll:
	mov ax, 1
	ret
endp


proc fastsetw uses di, dest:dword, what:word, len:word
	mov es, [word ptr dest+2]
	mov di, [word ptr dest]

	mov cx, [len]
	mov ax, [what]

	rep stosw
	ret
endp


; statDisp is an ultra-high speed output routine. this is because the
; status screen is updated once a second when waiting for user input, and
; between every character entered. this needs to be a quick update to be
; invisible to a user when the bbs is running on an XT. This gets most of
; its speed by not touching the cursor position, reading or writing. It
; also is faster than a directchar loop because there is only one call
; for each string, and the output is always directed to the phsyScreen,
; never the dgLogiScreen. Therefore this routine is limited in application,
; but well worth the few bytes of .EXE
proc statDisp uses ds di si, row:word, col:word, attr:word, str:dword
	mov di, [physScreen]
	mov es, [physScreen+2]

	mov al, [conCols]
	mul [byte ptr row]
	shl ax, 1
	shl [col], 1

	add di, ax
	add di, [col]

	mov ds, [word ptr str+2]
	mov si, [word ptr str]

	mov ah, [byte ptr attr]

sd_loop:
	lodsb
	or al, al
	jz sd_done
	stosw
	jmp short sd_loop

sd_done:
	ret
endp

proc gmode
	mov ah, 0fh
	mov bh, 0
	xor cx, cx
	int 10h
	mov ah, 0
	ret
endp

proc curshalf
	call gmode

	cmp ax, 7
	jne ch_color

	cmp [conMode], 1002
	je ch_color

	mov cx, 060dh
	jmp short ch_set

ch_color:
	mov cx, 0307h

ch_set: mov ah, 1
	mov bh, 0
	int 10h
	ret
endp


proc curson
	call gmode

	cmp ax, 7
	jne co_color

	cmp [conMode], 1002
	je co_color

	mov cx, 0c0dh
	jmp short co_set

co_color:
	mov cx, 0607h

co_set: mov ah, 1
	mov bh, 0
	int 10h
	ret
endp

proc cursoff
	mov ah, 1
	mov bh, 0
	mov cx, 2607h
	int 10h
	ret
endp

;proc putatrb uses di es, ccol:word, crow:word, len:word, clr:byte
;	cld
;	mov di, [dgLogiScreen]
;	mov es, [dgLogiScreen+2]
;	mov bl, [conCols]
;
;	mov ax, [crow]
;	mul bl
;	add ax, [ccol]
;	shl ax, 1
;	add di, ax
;
;	mov cx, [len]
;	mov al, [clr]
;
;pa_lp:	inc di
;	stosb
;	loop pa_lp
;
;	ret
;endp


;proc putmsgnc uses ds di si, row:word, col:word, str:dword
;	cld
;
;	mov di, [physScreen]
;	mov es, [physScreen+2]
;
;	mov al, [conCols]
;	mul [byte ptr row]
;	shl ax, 1
;	shl [col], 1
;
;	add di, ax
;	add di, [col]
;
;	mov ds, [word ptr str+2]
;	mov si, [word ptr str]
;
;pm_loop:lodsb
;	or al, al
;	jz pm_done
;	stosb
;	inc di
;	jmp short pm_loop
;
;pm_done:
;	ret
;endp

proc critical_error
	mov al, 3	; fail error
	iret
endp

end
