delorie.com/archives/browse.cgi   search  
Mail Archives: opendos/2003/12/04/09:58:08

X-Authentication-Warning: delorie.com: mail set sender to opendos-bounces using -f
Date: Thu, 4 Dec 2003 09:56:42 -0500
Message-Id: <200312041456.hB4EugkR014652@envy.delorie.com>
From: DJ Delorie <dj AT delorie DOT com>
To: opendos AT delorie DOT com
In-reply-to: <3FCE4C60.20586.3407B89@localhost> (shadow@shadowgard.com)
Subject: Re: ANSI.SYS
References: <3FCE1EC1 DOT 3772 DOT 294B30C AT localhost> (shadow AT shadowgard DOT com) <3FCE4C60 DOT 20586 DOT 3407B89 AT localhost>
Reply-To: opendos AT delorie DOT com
Errors-To: nobody AT delorie DOT com
X-Mailing-List: opendos AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

> > I used to have a VT52.SYS driver too...
> > 
> > Oh wait, I still do :-)
> 
> Can I have a copy?

I make no guarantees about how well it works on modern computers...


	title	VT-52
; Copyright 1989 DJ Delorie

	.286c

check_ega	equ	1

dqq	struc
ofs	dw	?
seg	dw	?
dqq	ends

wqq	struc
w	dw	?
wqq	ends

bqq	struc
b	db	?
bqq	ends

rqq	struc
len	db	?
unit	db	?
code	db	?
status	dw	?
q1	dd	?
q2	dd	?
single	db	?			; single byte read (no wait)
trans	dd	?
count	dw	?
rqq	ends

cesc	struc
	db	?
	dw	?
cesc	ends

cocall	macro	which
	call	[which]
	pop	[which]
	endm

cseg	segment	byte
	assume	cs:cseg,ds:nothing,es:nothing,ss:nothing
	org	0

success	equ	0100h
busy	equ	0200h

header	label	near
	dd	-1
	dw	8003h			; replaces stdin and stdout
	dw	strat
	dw	intr
	db	'VT52$   '

req	dd	?

	dw	200 dup (?)
stack	label	word

strat	proc	far
	mov	cs:[req].ofs,bx
	mov	cs:[req].seg,es
	ret
strat	endp

intr	proc	far
	sti
	push	ds
	push	es
	push	ax
	push	bx
	push	cx
	push	dx
	push	di
	push	si
	mov	ax,cs
	mov	ds,ax
	les	bx,req
	mov	si,offset cmd_table
	mov	cl,es:[bx].code
	mov	ch,0
	shl	cx,1
	add	si,cx

	call	[si].w

	les	bx,req
	mov	es:[bx].status,ax
	pop	si
	pop	di
	pop	dx
	pop	cx
	pop	bx
	pop	ax
	pop	es
	pop	ds
	ret

cmd_table:
	dw	cmd_init	; init
	dw	cmd_none	; media check
	dw	cmd_none	; bpb
	dw	cmd_none	; ioctl input
	dw	cmd_input	; input
	dw	cmd_input_now	; nondestructive input no wait
	dw	cmd_input_stat	; input status
	dw	cmd_input_flush	; input flush
	dw	cmd_output	; output
	dw	cmd_output	; output with verify
	dw	cmd_output_stat	; output status
	dw	cmd_none	; output flush
	dw	cmd_none	; ioctl output
	dw	10 dup(cmd_none)

intr	endp

cmd_none	proc 	near
	mov	ax,success
	ret
cmd_none	endp

;============================================================================

old_int10	dd	?
fgc		db	?
bgc		db	?
has_ega		db	?		; 1=EGA, 0=other
getc		dw	?		; for cocalls

int10:
	cmp	ah,14
	je	fnct_14
	cmp	ax,0003h		; mode select
	je	fnct_3
;	cmp	ah,1			; cursor type set
;	je	fnct_1
	cmp	ah,0			; other mode set
	je	mode_0
	jmp	cs:[old_int10]

mode_0:
	pushf
	call	cs:[old_int10]
	pusha
	mov	ah,3
	mov	bh,0
	int	10h
	mov	ah,1
	int	10h
	popa
	iret

fnct_1:
	pusha
	push	ds
	mov	ax,0
	mov	ds,ax
	mov	ds:[460h],cx		; store cursor mode now
	mov	al,ds:[485h]		; bytes per character
	cmp	al,10
	je	ch_ok
	sub	al,8			; difference
	cmp	cl,5
	jbe	cl_ok
	add	cl,al
cl_ok:
	cmp	ch,5
	jbe	ch_ok
	add	ch,al
ch_ok:
	mov	dx,3d4h
	mov	al,10			; cursor start
	mov	ah,ch
	out	dx,ax
	inc	al			; cursor end
	mov	ah,cl
	out	dx,ax
	pop	ds
	popa
	iret

fnct_3:
	sti
	pusha
	push	ds
	push	cs
	pop	ds
	call	mode_3_setup
	pop	ds
	popa
	iret

fnct_14:
	sti
	pusha
	push	ds
	push	cs
	pop	ds
	cocall	getc
	pop	ds
	popa
	iret

;============================================================================

max_col		db	?
max_row		db	?
cur_mode	db	?
cur_page	db	?
temp		db	?
save_cur	dw	0
color_save	dw	0
wrap		db	0
crt_mode	db	0
 status_line	equ	1
 lines43	equ	2
intense		db	0		; 1=intense

tty_write_init:
	pop	[getc]		; first time - pop only
	mov	fgc,7
	mov	bgc,0

tty_write:
	cocall	getc			; get character from user
	push	ax
	mov	ah,15
	int	10h
	mov	[cur_mode],al
	mov	[cur_page],bh
	mov	ah,3
	int	10h
	push	es
	xor	ax,ax
	mov	es,ax
	mov	al,es:[484h]
if check_ega
	cmp	has_ega,1
	je	ega_rows
	mov	al,24			; if not EGA, assume 25 lines.
ega_rows:
endif
	test	[crt_mode],status_line
	jz	tty_no_status
	dec	al
tty_no_status:
	mov	[max_row],al
	mov	al,es:[44ah]
	dec	al
	mov	[max_col],al
	pop	es
	pop	ax			; cursor in (dh,dl) cur_page in bh
	cmp	al,7
	je	print_bell
	cmp	al,8
	je	print_bs
	cmp	al,9
	je	print_tab
	cmp	al,10
	je	print_lf
	cmp	al,13
	je	print_cr
	cmp	al,27
	jne	print_char_do
	jmp	escape
print_char_do:
	jmp	print_char

print_bell:
	call	fast_beep
	jmp	tty_write

print_tab:
	and	dl,not 7
	add	dl,8
	jmp	set_cursor

print_bs:
	cmp	dl,0
	je	set_cursor
	dec	dl
	jmp	set_cursor

print_cr:
	mov	dl,0
	jmp	set_cursor

print_lf:
	cmp	dh,[max_row]
	jae	scroll_up
	inc	dh

set_cursor:
	mov	ah,2
	mov	bh,[cur_page]
	int	10h
	jmp	tty_write

scroll_up:
	mov	bh,[cur_page]
	mov	dh,[max_row]
	mov	ah,2
	int	10h
	mov	ax,0601h		; scroll one line up
	mov	dh,[max_row]
	mov	dl,[max_col]
	xor	cx,cx
	mov	bh,[bgc]
	shl	bh,1
	shl	bh,1
	shl	bh,1
	shl	bh,1
	or	bh,[fgc]
	cmp	[cur_mode],3
	jbe	do_scroll
	cmp	[cur_mode],7
	je	do_scroll
	mov	bh,0
do_scroll:
	int	10h
	cmp	[intense],1
	jne	no_intense
	mov	dx,3d8h
	in	al,dx
	and	al,0dfh
	out	dx,al
no_intense:
	jmp	tty_write

escape:
	cocall	getc
	mov	si,offset esc_lookup_table
escape_loop:
	cmp	[si],al
	je	esc_found
	cmp	[si].b,0
	je	esc_invalid
	add	si,3
	jmp	escape_loop

esc_invalid:
	jmp	tty_write

esc_found:
	jmp	[si+1]

esc_lookup_table	label	byte
	cesc	<'+',offset esc_plus>
	cesc	<'-',offset esc_minus>
	cesc	<'[',offset esc_ansi>
	cesc	<'A',offset esc_cA>
	cesc	<'B',offset esc_cB>
	cesc	<'C',offset esc_cC>
	cesc	<'D',offset esc_cD>
	cesc	<'E',offset esc_cE>
	cesc	<'H',offset esc_cH>
	cesc	<'I',offset esc_cI>
	cesc	<'J',offset esc_cJ>
	cesc	<'K',offset esc_cK>
	cesc	<'Y',offset esc_cY>
	cesc	<'b',offset esc_b>
	cesc	<'c',offset esc_c>
	cesc	<'j',offset esc_j>
	cesc	<'i',offset esc_i>
	cesc	<'k',offset esc_k>
	cesc	<'m',offset esc_m>
	cesc	<'s',offset esc_s>
	cesc	<'w',offset esc_w>
	cesc	<0,0>

;-----------------------------------------------------------------------------
esc_plus:
if check_ega
	cmp	has_ega,1
	jne	plus_exit
endif
	cmp	[max_row],40
	ja	plus_exit
	or	[crt_mode],lines43
	mov	ax,0003h
	int	10h
plus_exit:
	jmp	tty_write

;------------------------------------------------------------------------------
esc_minus:
if check_ega
	cmp	has_ega,1
	jne	plus_exit
endif
	cmp	[max_row],30
	jb	minus_exit
	and	[crt_mode],not lines43
	mov	ax,0003h
	int	10h
minus_exit:
	jmp	tty_write

;------------------------------------------------------------------------------
esc_ansi:
next_digit:
	cocall	getc
	cmp	al,';'
	je	next_digit
	cmp	al,'0'
	jb	end_digits
	cmp	al,'9'
	ja	end_digits
	jmp	next_digit

end_digits:
	cmp	al,'J'
	je	clear_screen
	jmp	tty_write
clear_screen:
	mov	ax,0600h
	mov	dh,[max_row]
	mov	dl,[max_col]
	xor	cx,cx
	mov	bh,[bgc]
	shl	bh,1
	shl	bh,1
	shl	bh,1
	shl	bh,1
	or	bh,[fgc]
	cmp	[cur_mode],3
	jbe	do_scroll2
	cmp	[cur_mode],7
	je	do_scroll2
	mov	bh,0
do_scroll2:
	int	10h
	mov	ah,2
	mov	bh,[cur_page]
	xor	dx,dx			; upper left corner
	int	10h
	test	[crt_mode],lines43
	jz	scroll_nocur
	mov	ah,1
	mov	cx,0007h
	int	10h
scroll_nocur:
	jmp	tty_write

;------------------------------------------------------------------------------
esc_cA:
	mov	ah,3
	mov	bh,[cur_page]
	int	10h
	cmp	dh,0
	je	end_cA
	dec	dh
	mov	bh,[cur_page]
	mov	ah,2
	int	10h
end_cA:
	jmp	tty_write

;------------------------------------------------------------------------------
esc_cB:
	mov	ah,3
	mov	bh,[cur_page]
	int	10h
	cmp	dh,[max_row]
	jae	end_cB
	inc	dh
	mov	bh,[cur_page]
	mov	ah,2
	int	10h
end_cB:
	jmp	tty_write

;------------------------------------------------------------------------------
esc_cC:
	mov	ah,3
	mov	bh,[cur_page]
	int	10h
	cmp	dl,[max_col]
	jae	end_cC
	inc	dl
	mov	ah,2
	mov	bh,[cur_page]
	int	10h
end_cC:
	jmp	tty_write

;------------------------------------------------------------------------------
esc_cD:
	mov	ah,3
	mov	bh,[cur_page]
	int	10h
	cmp	dl,0
	je	end_cD
	dec	dl
	mov	ah,2
	mov	bh,[cur_page]
	int	10h
end_cD:
	jmp	tty_write

;------------------------------------------------------------------------------
esc_cE:
	jmp	clear_screen

;------------------------------------------------------------------------------
esc_cH:
	mov	ah,2
	mov	bh,[cur_page]
	xor	dx,dx
	int	10h
	jmp	tty_write

;------------------------------------------------------------------------------

esc_cI:
	mov	bh,[cur_page]
	mov	dh,[max_row]
	mov	ah,2
	int	10h
	mov	ax,0701h		; scroll one line up
	mov	dh,[max_row]
	mov	dl,[max_col]
	xor	cx,cx
	mov	bh,[bgc]
	shl	bh,1
	shl	bh,1
	shl	bh,1
	shl	bh,1
	or	bh,[fgc]
	cmp	[cur_mode],3
	jbe	do_dscroll
	cmp	[cur_mode],7
	je	do_dscroll
	mov	bh,0
do_dscroll:
	int	10h
	jmp	tty_write

;------------------------------------------------------------------------------

esc_cJ:
	mov	ah,3
	mov	bh,[cur_page]
	int	10h
	mov	ch,dh
	inc	ch
	mov	ax,0600h
	mov	dh,[max_row]
	mov	dl,[max_col]
	mov	cl,0
	mov	bh,[bgc]
	shl	bh,1
	shl	bh,1
	shl	bh,1
	shl	bh,1
	or	bh,[fgc]
	cmp	[cur_mode],3
	jbe	do_cleareos
	cmp	[cur_mode],7
	je	do_cleareos
	mov	bh,0
do_cleareos:
	int	10h
	; fall through to esc-K

;------------------------------------------------------------------------------
esc_cK:
	mov	ah,3
	mov	bh,[cur_page]
	int	10h
	push	dx
	neg	dl
	add	dl,[max_col]
	inc	dl
	mov	cl,dl
	xor	ch,ch
	mov	al,' '
	mov	bh,[cur_page]
	mov	ah,9
	mov	bl,[bgc]
	shl	bl,1
	shl	bl,1
	shl	bl,1
	shl	bl,1
	or	bl,[fgc]
	cmp	[cur_mode],3
	jbe	do_scroll3
	cmp	[cur_mode],7
	je	do_scroll3
	mov	bl,0
do_scroll3:
	int	10h
	pop	dx
	jmp	set_cursor

;------------------------------------------------------------------------------
esc_cY:
	cocall	getc
	sub	al,' '
	cmp	al,'s'-' '
	jne	skip_status_line
	mov	al,[max_row]
	inc	al
skip_status_line:
	mov	[temp],al
	cocall	getc
	sub	al,' '
	mov	dh,[temp]
	mov	dl,al
	mov	ah,2
	mov	bh,[cur_page]
	int	10h
	jmp	tty_write

;------------------------------------------------------------------------------
esc_b:
	mov	ax,1003h		; set blink
	mov	bl,1
	int	10h
	mov	[intense],0
	jmp	tty_write

;------------------------------------------------------------------------------
esc_c:
	cocall	getc
	call	hex2dec
	mov	[temp],al
	cocall	getc
	call	hex2dec
	mov	ch,[temp]
	mov	cl,al
	mov	ah,1
	int	10h
	jmp	tty_write

;------------------------------------------------------------------------------
esc_i:
	mov	ax,1003h		; set intensify
	mov	bl,0
	int	10h
	mov	[intense],1
	mov	dx,3d8h
	in	al,dx
	and	al,0dfh
	out	dx,al
	jmp	tty_write

;------------------------------------------------------------------------------
esc_j:
	mov	ah,3
	mov	bh,[cur_page]
	int	10h
	mov	[save_cur],dx
	jmp	tty_write

;------------------------------------------------------------------------------
esc_k:
	mov	ah,2
	mov	bh,[cur_page]
	mov	dx,[save_cur]
	int	10h
	jmp	tty_write

;------------------------------------------------------------------------------
esc_m:
	cocall	getc
	cmp	al,'s'
	je	save_color
	cmp	al,'r'
	je	restore_color
	cmp	al,'*'
	je	esc_m_fgsame
	call	hex2bin
	mov	[fgc],al
esc_m_fgsame:
	cocall	getc
	cmp	al,'*'
	je	esc_m_bgsame
	call	hex2bin
	mov	[bgc],al
esc_m_bgsame:
	jmp	tty_write

save_color:
	mov	al,[fgc]
	mov	ah,[bgc]
	mov	[color_save],ax
	jmp	tty_write

restore_color:
	mov	ax,[color_save]
	mov	[fgc],al
	mov	[bgc],ah
	jmp	tty_write

;------------------------------------------------------------------------------
esc_s:
	cocall	getc
	cmp	al,'1'
	je	enable_status_line
	cmp	al,'0'
	je	disable_status_line
finished_status_line:
	jmp	tty_write

enable_status_line:			; turn status line on
	test	[crt_mode],status_line
	jnz	finished_status_line
	mov	ah,3
	mov	bh,[cur_page]
	int	10h
	dec	[max_row]
	or	[crt_mode],status_line
	cmp	dh,[max_row]
	jbe	finished_status_line
	jmp	scroll_up

disable_status_line:			; turn status line off
	test	[crt_mode],status_line
	jz	finished_status_line
	inc	[max_row]
	and	[crt_mode],not status
	mov	ah,3
	mov	bh,[cur_page]
	int	10h
	push	dx
	mov	dh,[max_row]
	xor	dl,dl
	mov	ah,2
	mov	bh,[cur_page]
	int	10h
	mov	ah,9
	mov	bl,[bgc]
	shl	bl,1
	shl	bl,1
	shl	bl,1
	shl	bl,1
	or	bl,[fgc]
	cmp	[cur_mode],3
	jbe	disable_status_2
	cmp	[cur_mode],7
	je	disable_status_2
	mov	bl,0
disable_status_2:
	mov	cl,[max_col]
	inc	cl
	xor	ch,ch
	mov	al,' '
	int	10h
	pop	dx
	mov	ah,2
	mov	bh,[cur_page]
	int	10h
	jmp	tty_write

;------------------------------------------------------------------------------
esc_w:
	cocall	getc
	and	al,1
	mov	[wrap],al
	jmp	tty_write

;------------------------------------------------------------------------------
print_char:
	push	dx
	mov	cx,1
	mov	ah,9
	mov	bl,[bgc]
	shl	bl,1
	shl	bl,1
	shl	bl,1
	shl	bl,1
	or	bl,[fgc]
	mov	bh,[cur_page]
	cmp	[cur_mode],3
	jbe	bgblink_ok
	and	bl,7fh
bgblink_ok:
	int	10h
	pop	dx
	cmp	dl,[max_col]
	jae	print_eol
	inc	dl
	jmp	set_cursor

print_eol:
	cmp	[wrap],1
	je	print_exit
	mov	dl,0
	cmp	dh,[max_row]
	je	print_eos
	ja	in_status_line
	inc	dh
	jmp	set_cursor

in_status_line:
	jmp	tty_write

print_eos:
	jmp	scroll_up

print_exit:
	jmp	tty_write

;============================================================================

hex2dec:
	sub	al,'0'
	cmp	al,9
	jbe	hex_ok
	sub	al,7
hex_ok:	and	al,0fh
	ret

hex2bin:
	call	hex2dec
	push	si
	mov	si,offset hex_tbl
	xor	ah,ah
	add	si,ax
	mov	al,[si]
	pop	si
	ret

hex_tbl	db	0,9,12,13,10,11,14,15,8,1,4,5,2,3,6,7

;============================================================================

mode_3_setup:
	pushf
	call	[old_int10]		; do mode set
	test	[crt_mode],lines43
	jz	mode_3_exit
	mov	ax,1112h
	mov	bx,0
	mov	dx,43
	int	10h
	mov	ah,1
	mov	cx,0007h
	int	10h
mode_3_exit:
	ret

;============================================================================

fast_beep	proc	near
	push	ax
	push	cx
	mov	al,0b6h
	out	43h,al
	mov	al,1500 and 255
	out	42h,al
	jmp	$+2
	mov	al,1500 shr 8
	out	42h,al
	in	al,61h
	push	ax
	or	al,3
	out	61h,al
	mov	cx,30000
	loop	$
	pop	ax
	out	61h,al
	pop	cx
	pop	ax
	ret
fast_beep	endp

;============================================================================

key_queue	db	?
queue_full	db	0

cmd_input:
	mov	cx,es:[bx].count
	lds	di,es:[bx].trans
cmd_input_loop:
	cmp	[queue_full],1
	je	cmd_input_queue
	mov	ah,0
	int	16h
	cmp	al,0
	jne	cmd_input_normal

	mov	[key_queue],ah
	mov	[queue_full],1
	jmp	cmd_input_normal

cmd_input_queue:
	mov	al,[key_queue]
	mov	[queue_full],0

cmd_input_normal:
	mov	[di],al
	inc	di
	loop	cmd_input_loop
	mov	ax,success
	ret

;============================================================================

cmd_input_now	proc	near
	cmp	[queue_full],1
	jne	cmd_input_now_int

	mov	al,[key_queue]
	mov	es:[bx].single,al
	mov	ax,success
	jmp	cmd_input_now_end

cmd_input_now_int:
	mov	ah,1
	int	16h
	mov	es:[bx].single,al
	mov	ax,success
	jnz	cmd_input_now_end

	or	ax,busy
cmd_input_now_end:
	ret
cmd_input_now	endp

;============================================================================

cmd_input_stat	proc	near
	cmp	[queue_full],1
	je	cmd_input_stat_end

	mov	ah,1
	int	16h
	mov	ax,success
	jnz	cmd_input_stat_end
	or	ax,busy
cmd_input_stat_end:
	ret
cmd_input_stat	endp

;============================================================================

cmd_input_flush	proc	near
	jmp	cmd_input_flush_end
	mov	[queue_full],0
	mov	ah,1
	int	16h
	jz	cmd_input_flush_end
	mov	ah,0
	int	16h
	jmp	cmd_input_flush
cmd_input_flush_end:
	mov	ax,success
	ret
cmd_input_flush	endp

;============================================================================

cmd_output	proc	near
	mov	cx,es:[bx].count
	lds	si,es:[bx].trans
cmd_output_loop:
	mov	ah,14
	mov	al,ds:[si]
	inc	si
	push	si
	push	cx
	int	10h
	pop	cx
	pop	si
	loop	cmd_output_loop
	mov	ax,success
	ret
cmd_output	endp

;============================================================================

cmd_output_stat	proc	near
	mov	ax,success
	ret
cmd_output_stat	endp

;============================================================================

cmd_init	proc	near

	mov	ax,cs
	mov	ds,ax

if check_ega
	push	bx
	mov	has_ega,0		; innocent until proven guilty
	mov	ax,1200h
	mov	bx,10h
	mov	cx,-1
	int	10h
	cmp	cx,-1
	je	no_ega
	mov	has_ega,1
no_ega:
	pop	bx
endif

	mov	getc,offset tty_write_init
	cocall	getc			; to initialize

	mov	ax,0
	mov	ds,ax

	mov	ax,ds:[40h]
	mov	old_int10.ofs,ax
	mov	ax,ds:[42h]
	mov	old_int10.seg,ax

	mov	ds:[40h].w,offset int10
	mov	ds:[42h].w,cs

	mov	ax,cs
	mov	ds,ax

	mov	dx,offset banner
	mov	ah,9			; print string
	int	21h

	mov	es:[bx].trans.ofs,offset cmd_init
	mov	es:[bx].trans.seg,cs
	mov	ax,success
	ret

cmd_init	endp


banner	db	'VT-52 emulator has been loaded.',13,10,'$'

cseg	ends

	end

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019