; *** Listing 6.2 ***
;
; Program to illustrate use of read mode 1 (color compare mode)
; to detect collisions in display memory. Draws a yellow line on a
; blue background, then draws a perpendicular green line until the
; yellow line is reached.
;
; Assembled with TASM 4.0, linked with TLINK 6.10
; Checked by Jim Mischel 11/21/94
;
stack	segment	word stack 'STACK'
	db	512 dup (?)
stack	ends
;
VGA_SEGMENT	EQU	0a000h
SCREEN_WIDTH	EQU	80	;in bytes
GC_INDEX		EQU	3ceh	;Graphics Controller Index register
SET_RESET	EQU	0	;Set/Reset register index in GC
ENABLE_SET_RESET EQU	1	;Enable Set/Reset register index in GC
COLOR_COMPARE	EQU	2	;Color Compare register index in GC
GRAPHICS_MODE	EQU	5	;Graphics Mode register index in GC
BIT_MASK		EQU	8	;Bit Mask register index in GC
;
code	segment	word 'CODE'
	assume	cs:code
Start	proc	near
	cld
;
; Select graphics mode 10h.
;
	mov	ax,10h
	int	10h
;
; Fill the screen with blue.
;
	mov	al,1		;blue is color 1
	call	SelectSetResetColor ;set to draw in blue
	mov	ax,VGA_SEGMENT
	mov	es,ax
	sub	di,di
	mov	cx,7000h
	rep	stosb		;the value written actually doesn't
				; matter, since set/reset is providing
				; the data written to display memory
;
; Draw a vertical yellow line.
;
	mov	al,14		;yellow is color 14
	call	SelectSetResetColor ;set to draw in yellow
	mov	dx,GC_INDEX
	mov	al,BIT_MASK
	out	dx,al		;point GC Index to Bit Mask
	inc	dx		;point to GC Data
	mov	al,10h
	out	dx,al		;set Bit Mask to 10h
	mov	di,40		;start in the middle of the top line
	mov	cx,350		;do full height of screen
VLineLoop:
	mov	al,es:[di]	;load the latches
	stosb			;write next pixel of yellow line (set/reset
				; provides the data written to display
				; memory, and AL is actually ignored)
	add	di,SCREEN_WIDTH-1 ;point to the next scan line
	loop	VLineLoop
;
; Select write mode 0 and read mode 1.
;
	mov	dx,GC_INDEX
	mov	al,GRAPHICS_MODE
	out	dx,al		;point GC Index to Graphics Mode register
	inc	dx		;point to GC Data
	mov	al,00001000b	;bit 3=1 is read mode 1, bits 1 & 0=00
				; is write mode 0
	out	dx,al		;set Graphics Mode to read mode 1,
				; write mode 0
;
; Draw a horizontal green line, one pixel at a time, from left
; to right until color compare reports a yellow pixel is encountered.
;
; Draw in green.
;
	mov	al,2		;green is color 2
	call	SelectSetResetColor ;set to draw in green
;
; Set color compare to look for yellow.
;
	mov	dx,GC_INDEX
	mov	al,COLOR_COMPARE
	out	dx,al		;point GC Index to Color Compare register
	inc	dx		;point to GC Data
	mov	al,14		;we're looking for yellow, color 14
	out	dx,al		;set color compare to look for yellow
	dec	dx		;point to GC Index
;
; Set up for quick access to Bit Mask register.
;
	mov	al,BIT_MASK
	out	dx,al		;point GC Index to Bit Mask register
	inc	dx		;point to GC Data
;
; Set initial pixel mask and display memory offset.
;
	mov	al,80h		;initial pixel mask
	mov	di,100*SCREEN_WIDTH
				;start at left edge of scan line 100
HLineLoop:
	mov	ah,es:[di]	;do a read mode 1 (color compare) read.
				; This also loads the latches.
	and	ah,al		;is the pixel of current interest yellow?
	jnz	WaitKeyAndDone	;yes-we've reached the yellow line, so we're
				; done
	out	dx,al		;set the Bit Mask register so that we
				; modify only the pixel of interest
	mov	es:[di],al	;draw the pixel. The value written is
				; irrelevant, since set/reset is providing
				; the data written to display memory
	ror	al,1		;shift pixel mask to the next pixel
	adc	di,0		;advance the display memory offset if
				; the pixel mask wrapped
;
; Slow things down a bit for visibility (adjust as needed).
;
	mov	cx,0
DelayLoop:
	loop	DelayLoop

	jmp	HLineLoop
;
; Wait for a key to be pressed to end, then return to text mode and
; return to DOS.
;
WaitKeyAndDone:
WaitKeyLoop:
	mov	ah,1
	int	16h
	jz	WaitKeyLoop
	sub	ah,ah
	int	16h		;clear the key
	mov	ax,3
	int	10h		;return to text mode
	mov	ah,4ch
	int	21h		;done
Start	endp
;
; Enables set/reset for all planes, and sets the set/reset color
; to AL.
;
SelectSetResetColor	proc	near
	mov	dx,GC_INDEX
	push	ax		;preserve color
	mov	al,SET_RESET
	out	dx,al		;point GC Index to Set/Reset register
	inc	dx		;point to GC Data
	pop	ax		;get back color
	out	dx,al		;set Set/Reset register to selected color
	dec	dx		;point to GC Index
	mov	al,ENABLE_SET_RESET
	out	dx,al		;point GC Index to Enable Set/Reset register
	inc	dx		;point to GC Data
	mov	al,0fh
	out	dx,al		;enable set/reset for all planes
	ret
SelectSetResetColor	endp
code	ends
	end	Start
