Skip to content

Instantly share code, notes, and snippets.

@wizzwizz4
Last active January 2, 2017 10:17
Show Gist options
  • Save wizzwizz4/37a203a3997e7b2c7979cc9191d3439b to your computer and use it in GitHub Desktop.
Save wizzwizz4/37a203a3997e7b2c7979cc9191d3439b to your computer and use it in GitHub Desktop.
An archive of the VT52 assembly code found at http://www.delorie.com/opendos//archives/browse.cgi?p=opendos/2003/12/04/09:58:08 (copied literally except possible memory corruption)
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment