page 60,132
write	macro	row, column, text, attribute
	mov	ah,13h	;Write string
	mov	al,1	;Move cursor
	mov	bh,0	;Page#
	mov	bl,attribute
	mov	dh,row
	mov	dl,column
	mov	ch,0
	mov	cl,text	;Char count in 1st byte
	mov	bp,offset text+1
	push	ds
	pop	es
	int	10h
	endm

code	segment public 'code'
	assume cs:code, ds:code
	org 100h
start:	jmp	begin

bar_pos	label	word
;column + row * 80
	dw	0 +70*80
 	dw	5 +70*80
	dw	10+70*80
 	dw	15+70*80
	dw	20+70*80
 	dw	25+70*80
	dw	30+70*80
 	dw	35+70*80
	dw	40+70*80
 	dw	45+70*80
	dw	50+70*80
 	dw	55+70*80
	dw	60+70*80
 	dw	65+70*80
	dw	70+70*80
 	dw	75+70*80

bar_size	label	word
; width in columns + height in rows*256
	dw	5 +170*256

dpal_table	label	byte	;default palette
	db	0,1,2,3,4,5,14h,7,38h,39h,3ah,3bh,3ch,3dh,3eh,3fh,0
pal_table	label	byte
	db	15 dup (0), 3ah, 0
curr_color	db	1
ega_color	db	1
single_step	db	0

hex	db	'0123456789ABCDEF'
top_text	db	28, 'EGA 64 color palette demo by'
myname	db	11, 'Paul Verket'
based_on	db	77, 'Based on examples from IBM Personal '
	db	'Computer Proceedings  Volume 2, Number 11'
rgb_title	db	48, 'R  R', 39d, ' G  G', 39d, ' B  B', 39d, 
	db	' = EGA value (hex) ', 10 dup (205), 190
rgb_arrow	db	1, 24
legend	db	71, '<Space> to single step, <Return> to run ',
	db	'continuously, <Escape> to exit'

clr_screen	proc	near
	mov	ax,0f00h
	int	10h
	xor	ah,ah
	int	10h
	ret
clr_screen	endp

xlat_color	proc	near
;This translates the BH register from a user palette where each bit
;equals X X R R'G G'B B'to the EGA card format 
;of     X X R'G'B'R G B
	push	ax
	push	cx
	mov	ax,0
	mov	cx,3
	rcl	bh,1	;Get rid of don't care bits
	rcl	bh,1
xlat1:	rcl	bh,1
	rcl	al,1	;Move in color
	rcl	bh,1
	rcl	ah,1	;Move in color'
	loop	xlat1	;Dec CX
	mov	cl,3
	shl	ah,cl	;shift color left by 3 bits
	or	ah,al
	mov	bh,ah
	pop	cx
	pop	ax
	ret
xlat_color	endp

graphics_colorbar	proc	near
	push	di	;save di
	push	si	;save si
	mov	al,05h
	mov	dx,03ceh	;graphics write mode register
	out	dx,al
	mov	al,02h	;change to write mode 2
	mov	dx,03cfh
	out	dx,al
	xor	si,si	;initialize si
	mov	al,0h
bar_loop:
	mov	bx,bar_size	;move bar size to be displayed
	push	si
	push	ax
	mov	ax,02h	;move multiplicand into ax
	mul	si	;multiply SI for table indexing
	mov	si,ax	;move index value to SI
	mov	bp,bar_pos[si]	;get bar position using index
	pop	ax	;recover value
	pop	si
	mov	cx,0a000h	;load regen area into CX
	mov	es,cx	;set seg reg to video buffer area

	xor	dx,dx	;clear dx
	mov	dl,bl	;load row
bar_fill:
	mov	cx,dx	;use as counter
	mov	di,bp
	rep	stosb
	mov	di,bp
	add	bp,80d
	dec	bh
	jnz	bar_fill
	inc	si
	inc	al
	cmp	si,15d
	jc	bar_loop

	mov	al,05h
	mov	dx,03ceh	;graphics write mode register
	out	dx,al
	mov	al,00h	;change to write mode 0 (BIOS default)
	mov	dx,03cfh
	out	dx,al
	pop	si
	pop	di
	ret
graphics_colorbar	endp

wr_hex	proc	near
	mov	ah,2	;Set cursor position
	mov	bh,0
	mov	dh,20d	;row
	mov	dl,46d	;col
	int	10h
	mov	al,ega_color	;print hex of color high nibble
	mov	cl,4
	shr	al,cl
	mov	ah,0
	mov	si,ax
	mov	al,hex[si]
	mov	ah,0eh	;write char
	mov	bl,0fh	;with attribute
	int	10h
	mov	ah,2	;Set cursor position
	mov	bh,0
	mov	dh,20d	;row
	mov	dl,47d	;col
	int	10h
	mov	al,ega_color	;print hex of color low nibble
	and	al,0fh
	mov	ah,0
	mov	si,ax
	mov	al,hex[si]
	mov	ah,0eh	;write char
	mov	bl,0fh	;with attribute
	int	10h
	ret
wr_hex	endp

color_bin	proc	near	;Write curr_color in binary
	push	ax
	push	bx
	push	cx
	push	dx
	mov	ah,curr_color
	mov	cl,3
	shl	ah,cl	;Drop don't care bits, 1st bit in carry
	mov	cx,6	;# bits left to print
	mov	dl,25	;starting column
nxt_bit:	jc	prt_one
	mov	al,'0'	;Print a zero
	jmp	prt_bit
prt_one:	mov	al,'1'	;Print a one
prt_bit:	push	cx
	push	ax
	mov	ah,2	;set cursor position
	mov	bh,0
	mov	dh,20d	;row
	int	10h
	pop	ax	;get the orig AL reg back
	push	ax
	mov	ah,0eh	;write char
	mov	bl,0fh	;with attribute
	int	10h	;write char
	pop	ax
	pop	cx
	add	dl,3	;Move cursor register to next position
	shl	ah,1	;Next bit
	loop	nxt_bit
	pop	dx
	pop	cx
	pop	bx
	pop	ax
	ret
color_bin	endp

begin:	mov	ah,0	;Set EGA to mode 10h
	mov	al,10h
	int	10h
	call	clr_screen
	mov	ah,10h	;Set initial palette
	mov	al,2
	mov	dx,offset pal_table
	push	ds
	pop	es
	int	10h
	call	graphics_colorbar

	write	0, 26, top_text, 11h
	write	2, 34, myname, 22h
	write	4,  0, based_on, 33h
	write	18,72, rgb_arrow, 0fh
	write	19,25, rgb_title, 0fh
	write	24, 0, legend, 0fh
vert:
	mov	dx,3dah	;check
	in	al,dx	;   for
	and	al,08h	;     vertical retrace
	jz	vert	;not in retrace, check again
vert2:	mov	dx, 3dah	;wait for
	in	al,dx
	and	al,08h	;     next occurrence
	cmp	al,08h
	je	vert2	;         of not in retrace
	push	ds
	pop	es
	cld		;shift palette values left by 1 (except 0, 15)
	mov	si,offset pal_table + 2
	mov	di,offset pal_table + 1
	mov	cx,13d
rep	movsb
	mov	bh,curr_color
	call	xlat_color
	mov	pal_table+14d,bh
	mov	ega_color,bh
	mov	ah,10h	;Set palette
	mov	al,2
	mov	dx,offset pal_table
	push	ds
	pop	es
	int	10h
	call	color_bin
	call	wr_hex
	inc	curr_color	;increment color
	and	curr_color,63d	;Only 64 palette defs allowed

;--DOS keyboard check
keychk:	mov	ah,0bh	;check input status
	int	21h
	cmp	al,0ffh	;Any key hit??
	je	chk_key
	cmp	single_step, 1	;Stop after each bar??
	je	keychk
	jmp	vert
chk_key:	mov	ah,07h	;character found so
	int	21h
	cmp	al,27d	;Check char for ESC
	je	exit
	cmp	al,32d	;Check for <space>
	jne	chk_ret
	cmp	single_step, 1	;If already stepping, do next colorbar
	je	vert
	mov	single_step, 1
	jmp	keychk
chk_ret:	cmp	al,13d	;Check for <Return>
	jne	vert
	mov	single_step, 0
	jmp	vert	

exit:	mov	ah,10h
	mov	al,02h
	push	ds
	pop	es
	mov	dx,offset dpal_table
	int	10h	;restore default palette
	mov	ax,0002h
	int	10h
	int	20h	; return to DOS
code	ends
	end	start
