Metropoli BBS
VIEWER: screen.asm MODE: TEXT (ASCII)
%TITLE  "Memory-Mapped Video Screen output routines"

;----------NOTE: you must call ScInit before calling anything else here !!
	IDEAL
	DOSSEG
	MODEL	small

MaxRow		EQU	25
MaxCol		EQU	80
MonoBase	EQU	0b000h
DefaultBase	EQU	0b800h

RECORD attrByte Blink:1, Background:3, Intensity:1, Foreground:3

BlinkMask	EQU	MASK	Blink
BackMask	EQU	MASK	Background
IntensityMask	EQU	MASK	Intensity
ForeMask	EQU	MASK	Foreground


	DATASEG

attribute	attrByte <0,0,7>
vBase 		DW	DefaultBASE
BytesPerRow = MaxCol * 2
row = 0
LABEL	ScRow	Word
REPT	MaxRow
	dw (row * BytesPerRow)
	row = row + 1
ENDM

	CODESEG

	PUBLIC	ScGotoXY, ScReadXY, ScPokeChar, ScPokeStr, ScClrRect
	PUBLIC  ScSetBack, ScSetFore, ScBright, ScDim, ScBlink
	PUBLIC  ScNoBlink, ScGetAttribute, ScSetAttribute, ScInit
%NEWPAGE
;---------------------------------------------------------------------
;  SetVidAddr - prepare video-RAM address
;---------------------------------------------------------------------
;    NOTE: private subroutine for ScPokeChr & ScPokeStr
; 	Input:	dh = row (0 is top line)
;		dl = column (0 is at far left)
;	Output: es:di = video RAM buffer address for (row,column)
;		NOTE: dh & dl are not checked!!
;	Registers:  bx,dx,di, es changed
;---------------------------------------------------------------------
PROC	SetVidAddr
	mov	es,[vBase]
	xor	bh,bh
	mov	bl,dh
	shl	bx,1
	mov	di, [scRow + bx]
	xor	dh,dh
	shl	dx,1
	add	di,dx
	ret
ENDP	SetVidAddr
%NEWPAGE
;---------------------------------------------------------------------
;  ScGotoXY - set cursor position
;---------------------------------------------------------------------
; 	Input:	dh = row (0 is top line)
;		dl = column (0 is at far left)
;	Output:	cursor in page 0 repositioned to (row,column)
;	Registers:  none
;---------------------------------------------------------------------
PROC	ScGotoXY
	push	ax
	push	bx
	mov	ah,15
	int	10h
	mov	ah,2
	int	10h
	pop	bx
	pop	ax
	ret
ENDP	ScGotoXY
%NEWPAGE
;---------------------------------------------------------------------
;  ScReadXY - get cursor position
;---------------------------------------------------------------------
; 	Input:  none
;	Output:	dh = row (0 is top line)
;		dl = column (0 is at far left)
;	Registers:  dx changed
;---------------------------------------------------------------------
PROC	ScReadXY
	push	ax
	push	bx
	push	cx
	mov	ah,15
	int	10h
	mov	ah,3
	int	10h
	pop	cx
	pop	bx
	pop	ax
	ret
ENDP	ScReadXY
%NEWPAGE
;---------------------------------------------------------------------
;  ScPokeChar - poke a character into the display
;---------------------------------------------------------------------
; 	Input:  al = ASCII character code
;		dh = row (0 is top line)        *
;		dl = column (0 is at far left)  *
;	Output:	character in al displayed at position (row,column)
;			*NOTE:Row & column values NOT Checked!!
;	Registers:  ax,bx,dx, di changed
;---------------------------------------------------------------------
PROC	ScPokeChar
	push	es
	call	SetVidAddr
	mov	ah,[attribute]
	stosw
	pop	es
	ret
ENDP	ScPokeChar
%NEWPAGE
;---------------------------------------------------------------------
;  ScPokeStr - poke a string into the display
;---------------------------------------------------------------------
; 	Input:  cx = number of characters to write
;		dh = row (0 is top line)        *
;		dl = column (0 is at far left)  *
;		ds:di = address of ASCII string (any format)
;	Output:	  *NOTE:Row & column values NOT Checked!!
;		  NOTE: any string terminator is ignored
;	Registers:  ax,bx,cx,dx, di,si changed
;---------------------------------------------------------------------
PROC	ScPokeStr
	push	es
	call	SetVidAddr
	mov	ah,[attribute]
	cld
@@10:
	lodsb
	stosw
	loop	@@10
	pop	es
	ret
ENDP	ScPokeStr
%NEWPAGE
;---------------------------------------------------------------------
;  ScClrRect - clear rectangular area on display
;---------------------------------------------------------------------
; 	Input:  ch,cl = row & column of upper left corner
;		dh,dl = row & column of lower left corner
;	Output:	  rectangle defined by ch,cl & dh,dl cleared
;		     to current attributes
;	Registers:  ax
;---------------------------------------------------------------------
PROC	ScClrRect
	mov	ah,6
	mov	al,0
	mov	bh,[attribute]
	int	10h
	ret
ENDP	ScClrRect

%NEWPAGE
;---------------------------------------------------------------------
;  ScSetBack - set background color (attribute)
;---------------------------------------------------------------------
; 	Input:  al = background color
;	Output:	background color set for ScPokeChar & ScPokeStr
;	Registers:  al
;---------------------------------------------------------------------
PROC	ScSetBack
IF Background GT 0
	push	cx
	mov	cl,Background
	shl	al,cl
	pop	cx
ENDIF
	and	al,BackMask
	and	[attribute], NOT BackMask
	or	[attribute],al
	ret
ENDP	ScSetBack
%NEWPAGE
;---------------------------------------------------------------------
;  ScSetFore - set foreground color (attribute)
;---------------------------------------------------------------------
; 	Input:  al = foreground color
;	Output:	foreground color set for ScPokeChar & ScPokeStr
;	Registers:  al
;---------------------------------------------------------------------
PROC	ScSetFore
IF Foreground GT 0
	push	cx
	mov	cl,Foreground
	shl	al,cl
	pop	cx
ENDIF
	and	al,ForeMask
	and	[attribute], NOT ForeMask
	or	[attribute],al
	ret
ENDP	ScSetFore
%NEWPAGE
;---------------------------------------------------------------------
;  ScBright  -	Turn on intensity bit
;  ScDim     -	Turn off intensity bit
;  ScBlink   -	Turn on blink bit
;  ScNoBlink -	Turn off blink bit
;---------------------------------------------------------------------
; 	Input:  none
;	Output:	attribute's intensity & blink bits modified
;	Registers:  none
;---------------------------------------------------------------------
PROC	ScBright
	or	[attribute], IntensityMask
	ret
ENDP	ScBright
PROC	ScDim
	and	[attribute], NOT IntensityMask
	ret
ENDP	ScDim
PROC	ScBlink
	or	[attribute], BlinkMask
	ret
ENDP	ScBlink
PROC	ScNoBlink
	or	[attribute], NOT BlinkMask
	ret
ENDP	ScNoBlink
%NEWPAGE
;---------------------------------------------------------------------
;  ScGetAttribute  -	get current attribute value
;---------------------------------------------------------------------
; 	Input:  none
;	Output:	 dl = current attribute value
;	Registers:  dl
;---------------------------------------------------------------------
PROC	ScGetAttribute
	mov	dl,[attribute]
	ret
ENDP	ScGetAttribute
%NEWPAGE
;---------------------------------------------------------------------
;  ScSetAttribute  - change attribute value
;---------------------------------------------------------------------
; 	Input:   al = new attribute value
;	Output:	  none: attribute value stored for later use
;	Registers:  none
;---------------------------------------------------------------------
PROC	ScSetAttribute
	mov	[attribute],al
	ret
ENDP	ScSetAttribute
%NEWPAGE
;---------------------------------------------------------------------
;  ScInit  -  initialize OUTPUT package
;---------------------------------------------------------------------
; 	Input:   none
;	Output:	  vBase initialized
;	Registers:  none
;---------------------------------------------------------------------
PROC	ScInit
	push	ax
	push	bx
	mov	ah,15
	int	10h
	cmp	al,7
	jne	@@10
	mov	[vBase],MonoBase
@@10:
	pop	bx
	pop	ax
	ret
ENDP	ScInit

	END

[ RETURN TO DIRECTORY ]