;-------------------------setbox routine begins--------------------------+
; NAME  SETBOX
;
; from BLUEBOOK OF ASSEMBLY ROUTINES FOR IBM PC & XT.
;         page :  137
;
; ROUTINE FOR FILLING A RECTANGULAR BOX WITH COLOR
;
; FUNCTION: This routine fills a rectangular box in the color graphics
; screen with a given color.
;
; INPUT: Upon entry:
;
;	x-coordinate of upper left corner is in x1
;	y-coordinate of upper left corner is in y1
;	x-coordinate of lower right corner is in x2
;	y-coordinate of lower right corner is in y2
;	color of the rectangle is in bits 0 and 1 of color
;
; OUTPUT: Just to the screen.
;
; REGISTERS USED:  No registers are modified.
;
; SEGMENTS REFERENCED:  Upon entry ES must point to the video RAM at
; 0B8000h and DS must point to the following lookup table for color
; masks:
;
; xtable	dw	0FFC0h, 0FFF0h, 0FFFCh, 0FFFFh
;		dw	03FC0h, 03FF0h, 03FFCh, 03FFFh
;		dw	00FC0h, 00FF0h, 00FFCh, 00FFFh
;		dw	003C0h, 003F0h, 003FCh, 003FFh
;
; ROUTINES CALLED:  None
;
; SPECIAL NOTES: No bounds checking is performed. The coordinates must
; be in range and in order.  That is, the following case must be true:
;
;	0 <= x1 <= x2 <= 319
;	0 <= xy <= y2 <= 119	
;
; ROUTINE TO FILL A RECTANGULAR BOX
;
setbox	proc	far
;
	push	si		; save registers
	push	di
	push	dx
	push	bx
	push	cx
	push	ax
;
; determine byte position for start
;
; get y contribution
	mov	ax,y1		; get starting y-coordinate
	mov	ah,al		; replicate for odd-even bank
	and	ax,1FEh		; just one bit gets moved
	sal	ax,1		; times 4
	sal	ax,1		; times 8
	sal	ax,1		; times 16
	mov	di,ax		; address gets 16 * y-coord
	and	di,7FFh		; not the odd-even bit
	sal	ax,1		; times 32
	sal	ax,1		; times 64
	add	di,ax		; address gets 80 * y-coord
;
; add in x contribution
	mov	ax,x1		; get x coord
	sar	ax,1		; divide
	sar	ax,1		; by 4
	add	di,ax		; beginning offset
;
; count for outer loop
	mov	cx,y2		; ending y-coord
	sub	cx,y1		; minus starting y coord
	inc	cx		; plus 1
;
; count for inner loop
	mov	si,x2		; ending x-coord
	sar	si,1		; divide
	sar	si,1		; by 4
	mov	ax,x1		; starting x-coord
	sar	ax,1		; divide
	sar	ax,1		; by 4
	sub	si,ax		; take the difference
;
; get the color
	mov	bx,color	; get the color
	and	bx,3		; just between 0 and 3
	mov	dl,cbytes[bx]	; look up color pattern
;
; determine mask for starting and ending bytes
	mov	bx,x1		; starting byte
	and	bx,3		; just the pixel posn
	sal	bx,1		; times 2
	sal	bx,1		; times 4
	mov	ax,x2		; ending byte
	and	ax,3		; just the pixel posn
	add	bx,ax		; 4 * starting-ending
	sal	bx,1		; 8 * starting + 2 * ending
	mov	bx,xtable[bx]	; look up the masks
;
; set up masked color bytes
	mov	dh,dl		; color for the left bytes
	mov	ah,dl		; color for the middle bytes
	and	dx,bx		; mask left and right color bytes
;
	cld			; forward
;
sboxloop:
	push	cx		; save count of outer loop
	push	di		; save initial byte posn
;
	mov	cx,si		; count for inner loop
;
; check for only one byte
	mov	al,bh		; get the mask
	jcxz	sboxloop2	; if ending byte coincides
;
; color leftmost byte of the scan line
	not	al		; reverse the mask for clearing
	and	al,es: [di]	; get byte from memory and clear pixels
	or	al,dh		; put color in place
; *** possibly changing this to xor will be useful ***
	stosb			; put the byte in place
;
; check for just two bytes
	dec	cx		; count the byte
	jcxz	sboxloop1	; done ?
;
; color middle byte of scan line
	mov	al,ah		; color for middle byte
	rep	stosb		; put middle bytes in place
;
; handle rightmost byte of scan line
;
; come here if two or more bytes
sboxloop1:
	mov	al,0FFh		; set the full mask
;
; in all cases come here to adjust the masks
sboxloop2:
	and	al,bl		; bring in right part of the mask
	and	dl,al		; clear left part of color if needed
;
; color the byte
	not	al		; reverse the mask for clearing
	and	al,es: [di]	; get byte from memory and clear pixels
	or	al,dl		; put pixels in the byte
; *** change to xor would be interesting ***
	stosb			; put byte back into video RAM
;
; compute next scan line
	pop	di		; restore address of left side of box
	test	di,2000h	; odd or even line ?
	jz	sboxloop3	; skip if even
	add	di,80		; add 80 bytes per line
;
sboxloop3:
	xor	di,2000h	; changes banks in any case
	pop	cx		; restore count for outer loop
	loop	sboxloop	; next scan line
;
	pop	ax		; restore registers
	pop	cx
	pop	bx
	pop	dx
	pop	di
	pop	si
;
	ret			; return
;
setbox	endp
;-------------------------setbox routine ends---------------------------+
