home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
cpm86
/
fmacs86.ark
/
VT200.A86
< prev
next >
Wrap
Text File
|
1989-02-09
|
20KB
|
748 lines
pagesize 86
v30 equ 1
;Porting FREEMACS to CCPM computers assuming VT200 console with 8 bit controls
;The following conventions must be maintained:
; 1) Never leave this module with DF=1.
; 2) Never destroy ES.
; 3) Never MOV AX,DATA, always use the copy in the appropriate segment register.
; 4) Return NC if a routine succeeds, or fulfills its goals.
if v30
;macros for NEC V20/V30 or Intel 80186/286
codemacro SHRW parm:ew,count:db ;shift word right by
db 0c1h ;immediate count
modrm 5,parm
db count
endm
codemacro SHLB parm:eb,count:db ;shift byte right by
db 0c0h ;immediate count
modrm 4,parm
db count
endm
codemacro PUSHW parm:dw ;push immediate word
db 068h
dw parm
endm
codemacro PUSHALL ;push all register
db 060h ;AX,CX,DX,BX,SP,BP,SI,DI
endm
codemacro POPALL ;pop all register
db 061h ;DI,SI,BP,SP,BX,DX,CX,AX
endm
endif
;
call_di equ word ptr 0[bp] ;\----------------/
call_si equ word ptr 2[bp] ; \ /
call_bp equ word ptr 4[bp] ; \ /
call_sp equ word ptr 6[bp] ;\\\\ saved by ////
call_bx equ word ptr 8[bp] ;//// PUSHALL \\\\
call_dx equ word ptr 10[bp] ; / \
call_cx equ word ptr 12[bp] ; / \
call_ax equ word ptr 14[bp] ;/----------------\
call_es equ word ptr 16[bp]
call_ds equ word ptr 18[bp]
;
;
c_rawio equ 06h
c_write equ 02h
c_writestr equ 09h
c_writeblk equ 6Fh
p_delay equ 8Dh
codemacro CCPM parm:db ;call CCPM
db 0b1h ! db parm ;mov cl,parm
db 0cdh ! db 0e0h ;int 0E0H
endm
data dseg word public
public max_screen_line
max_screen_line db 21
esc equ 1Bh
dcs equ 90h
csi equ 9Bh ;control string introducer chars
st equ 9Ch
ss2 equ 8Eh
ss3 equ 8Fh
soh equ 01h
stx equ 02h
etx equ 03h
bs equ 08h
cr equ 0Dh
lf equ 0Ah
sho equ 0Eh ;shift out character
shi equ 0Fh ;shift in character
init_cons db esc,'[62;0"p' ;set vt200 mode 8-bit controls
db csi,'H' ;cursor to home
db csi,'2J' ;erase to end of screen
db csi,'0m' ;all attributes off
db csi,'2l' ;unlock keyboard
db csi,'1;22r' ;set scrolling region
db esc,')0' ;designate Special Graphics to G1
;____________________________________________________________________________
;now we are (pre-)defining the user programable
;function keys to return an artificial CSI-sequence
;THIS CODE IS INSTALLATION DEPENDANT !!!!!
db dcs,'0;1|' ;clear user function keys
db '17/9B35377E;' ;User F6
db '18/9B35387E;' ;User F7
db '19/9B35397E;' ;User F8
db '20/9B36307E;' ;User F9
db '21/9B36317E;' ;User F10
db '23/1B;' ;User F11 = <ESC> or C-[
db '24/08;' ;User F12 = <BS> or C-H
db '25/0A;' ;User F13 = <LF> or C-J
db '26/9B36367E;' ;User F14
db '28/9B36387E;' ;User Help
db '29/9B36397E;' ;User Do
db '31/9B37317E;' ;User F17
db '32/9B37327E;' ;User F18
db '33/9B37337E;' ;User F19
db '34/9B37347E',st;User F20
keypad_mode_str db esc,'=' ;Application Keypad
db '$'
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;______________________________________________________________________________
;the following holds true only for our own standard terminal setup at
;the University of TUEBINGEN.
;THIS CODE IS INSTALLATION DEPENDANT !!!!!
uninit_cons db dcs,'0;1|' ;reset user keys to BASF-PCI (SHIT MVS)
db '17/1B34;' ;F6 <ESC>4 = return
db '18/1B32;' ;F7 <ESC>2 = split
db '19/1B39;' ;F8 <ESC>9 = swap
db '20/1B35;' ;F9 <ESC>5 = rfind
db '21/1B36;' ;F10 <ESC>6 = rchange
db '23/1B;' ;F11 = <ESC>
db '24/08;' ;F12 = <BS>
db '25/0A;' ;F13 = <LF>
db '26/01;' ;F14 = <SOH> = home
db '28/1B31;' ;HELP <ESC>1 = help
db '29/1B33;' ;DO <ESC>3 = end
db '31/1B37;' ;F17 <ESC>7 = up
db '32/1B38;' ;F18 <ESC>8 = down
db '33/1B30;' ;F19 <ESC>0 = left
db '34/1B2D',st ;F20 <ESC>- = right
db esc,'c' ;recall initial terminal parameters
db '$'
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;
roll_dn_string db csi,'H',csi,'1L$'
roll_up_string db csi,'H',csi,'1M$'
ins_line_string equ roll_dn_string+2
del_line_string equ roll_up_string+2
cur_pos_string db csi,'ror;colH$'
clear_to_eol_string db csi,'K$'
sv_cursor_string db esc,'7$'
rs_cursor_string db esc,'8$'
rvideo_string db csi,'0;1;7m$'
key_buffer dw 0
ss3_scan_tab db 'ABCDMPQRSmlnpqrstuvwxy'
Comma_key db 'Comma'
LPar_key db 'LPar'
RPar_key db 'RPar'
delete_string db '*Delete'
ctrl_string db '*C-'
csi_name_tab db 41h,07,'Scan-up'
db 42h,09,'Scan-down'
db 43h,10,'Scan-right'
db 44h,09,'Scan-left'
db 01h,04,'Find'
db 02h,11,'Insert-here'
db 03h,06,'Remove'
db 04h,06,'Select'
db 05h,11,'Prev-Screen'
db 06h,11,'Next-Screen'
db 17h,02,'F6'
db 18h,02,'F7'
db 19h,02,'F8'
db 20h,02,'F9'
db 21h,03,'F10'
db 23h,03,'F11'
db 24h,03,'F12'
db 25h,03,'F13'
db 26h,03,'F14'
public breakchar ; /this is normally the "Help" key,
db 28h,05,'BREAK' ;< but here we'll use it as BREAK,
breakchar equ 28h*256+csi ; \for HELP use user's key "UHelp"
db 29h,02,'Do' ; \ THIS CODE IS INSTALLATION DEPENDANT !!
db 31h,03,'F17'
db 32h,03,'F18'
db 33h,03,'F19'
db 34h,03,'F20'
;____________________________________________________________________________
;*** PROGRAMMED user keys ***
;THIS CODE IS INSTALLATION DEPENDANT !!!!!
db 57h,03,'UF6'
db 58h,03,'UF7'
db 59h,03,'UF8'
db 60h,03,'UF9'
db 61h,04,'UF10'
db 63h,04,'UF11'
db 64h,04,'UF12'
db 65h,04,'UF13'
db 66h,04,'UF14'
db 68h,04,'Help' ;<"UHelp" Reserved for Help !!!
db 69h,02,'Do' ;<"UDo" = "Do" !!!
db 71h,04,'UF17'
db 72h,04,'UF18'
db 73h,04,'UF19'
db 74h,04,'UF20'
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;
db 00h,07,'<?CSI?>'
ss3_name_tab db 41h,07,'Scan-up'
db 42h,09,'Scan-down'
db 43h,10,'Scan-right'
db 44h,09,'Scan-left'
db 'M',05,'Enter'
db 'P',03,'PF1'
db 'Q',03,'PF2'
db 'R',03,'PF3'
db 'S',03,'PF4' ;<< ESCAPE to terminal handler commands
db 'm',08,'KP-minus'
db 'l',08,'KP-comma'
db 'n',08,'KP-point'
db 'p',04,'KP-0'
db 'q',04,'KP-1'
db 'r',04,'KP-2'
db 's',04,'KP-3'
db 't',04,'KP-4'
db 'u',04,'KP-5'
db 'v',04,'KP-6'
db 'w',04,'KP-7'
db 'x',04,'KP-8'
db 'y',04,'KP-9'
db 00h,07,'<?SS3?>'
unknown_key_string db 0,7,'Unknown'
font_select_string db shi,csi,'0' ;all attributes off
font_attribs rb 12
curr_font db 0
special_font_string db csi,'0;1m' ;bold
db sho,'$'
special_chars db 66h ;00: any undefined
db 60h ;01: visi space
db 61h ;02: visi tab
db 6Eh ;03: more character
db 68h ;04: visible newline
special_chars_lng equ (offset $) - (offset special_chars)
ctrl_char_string db esc,'7'
db csi,'0;1m' ;bold
ctrl_char db '?'
db esc,'8'
db csi,'C$'
help_buffer rb 16
temp equ help_buffer
;data ends
code cseg byte public
public init_entry
init_entry:
call prolog
mov dx,offset init_cons
ccpm c_writestr
epilog: mov sp,bp
if v30
popall
else
pop di ! pop si ! pop bp ! pop ax ;skip sp
pop bx ! pop dx ! pop cx ! pop ax
endif
pop es ! pop ds ! ret
prolog: pop prolog_return
push ds ! push es
if v30
pushall
else
push ax ! push cx ! push dx ! push bx
push sp ! push bp ! push si ! push di
endif
mov bp,sp ! mov ds,own_ds
jmp prolog_return
prolog_return rw 1
own_ds dw seg key_buffer
public uninit_exit
uninit_exit:
call prolog
mov dx,offset uninit_cons
ccpm c_writestr
mov dx,10 ;wait 10 clock ticks ..
ccpm p_delay ;.. for terminal recall
jmps epilog
public check_for_key
check_for_key:
;return zr,ax=0 if no key is waiting.
;return nz,ax=key if a key is waiting, but don't input the key yet.
call prolog ! mov ax,key_buffer ;last key is in buffer ?
mov call_ax,ax
or ax,ax ! jnz epilog
mov dl,0ffh ! ccpm c_rawio ;ask CCPM for a key present
check_for_key_0: xor ah,ah
;
cmp al,csi ! jne check_for_key_1
mov dl,0fdh ! ccpm c_rawio ;get first char. after CSI
cmp al,'A' ! jb check_for_csi_1 ;check for cursor keys
cmp al,'D' ! jbe check_for_csi_3
check_for_csi_1:
cmp al,'1' ! jb check_for_key_err ;not a CSI key
cmp al,'9' ! ja check_for_key_err
and al,0fh ! mov temp,al
mov dl,0fdh ! ccpm c_rawio ;get second char after CSI
cmp al,'~' ! je check_for_csi_2 ;end of CSI key
cmp al,'0' ! jb check_for_key_err
cmp al,'9' ! ja check_for_key_err
and ax,0fh
if v30
shlb temp,4 ! add temp,al ;form decimal packed
else
mov cl,4 ! shl temp,cl ! add temp,al
endif
mov dl,0fdh ! ccpm c_rawio ;get third char. after CSI
cmp al,'~' ! jne check_for_key_err ;must be '~'
check_for_csi_2: mov al,temp
check_for_csi_3: mov ah,csi
jmps check_for_key_2 ;save CSI code
check_for_key_1:
;check for SS3 key
cmp al,ss3 ! jne check_for_key_2
mov dl,0fdh ! ccpm c_rawio ;get first char after SS3
push ds ! pop es
mov di,offset ss3_scan_tab
mov cx,length ss3_scan_tab
repne scasb ;scan SS3 key table
jne check_for_key_err ;key error
cmp al,'S' ! je handler_seq ;special VT200 handler command sequence
mov ah,ss3
;
check_for_key_2:
mov key_buffer,ax ;save key
mov call_ax,ax ; and return it
or ax,ax ! jmp epilog
check_for_key_err:
call ring_the_bell
xor ax,ax ! jmps check_for_key_2
handler_seq:
;test for special terminal handler command sequences by PF4
call get_ss3_seq ;get the next SS3 sequence
cmp al,'p' ! jb handler_seq_PF4 ;not a decimal ASCII
cmp al,'r' ! ja check_for_key_err
;
;get ASCII char in decimal representation (000-255)
sub al,'p' ! mov cl,10 ! mul cl
push ax ! call get_ss3_seq ! pop dx
sub al,'p' ! jb check_for_key_err
cmp al,9 ! ja check_for_key_err
add ax,dx ! mov cl,10 ! mul cl
push ax ! call get_ss3_seq ! pop dx
sub al,'p' ! jb check_for_key_err
cmp al,9 ! ja check_for_key_err
add ax,dx ! cmp ax,255
ja check_for_key_err
mov ah,'B' ! jmps check_for_key_2 ;signal bin key
;
handler_seq_PF4:
;if double PF4 then return PF4
cmp al,'S' ! jne handler_seq_PF3
mov ah,ss3 ! jmp check_for_key_2
;
handler_seq_PF3:
;if "PF4 PF3" then alter the keypad mode (application <--> numeric)
cmp al,'R' ! jne handler_seq_err ;*** yet !!!! --- error ----
xor keypad_mode_str+1,03h ;toggle mode
mov dx,offset keypad_mode_str
ccpm c_writestr
xor ax,ax ! jmp check_for_key_2
;
handler_seq_err:
jmp check_for_key_err
get_ss3_seq:
mov dl,0fdh ! ccpm c_rawio
cmp al,ss3 ! jne handler_seq_err
mov dl,0fdh ! ccpm c_rawio
xor ah,ah ! ret
public get_key_value
get_key_value:
;exit with ax=key code.
push ds ! mov ds,own_ds
xor ax,ax ! xchg ax,key_buffer ;get key and clear buffer
pop ds ! or ax,ax ! jz $+3 ! ret
if v30
pushw offset get_key_value ;return from check_key_value_0
else
mov ax,offset get_key_value ! push ax
endif
call prolog
mov dl,0fdh ! ccpm c_rawio ;read char from console
jmp check_for_key_0 ;check control codes
public decode_key
decode_key:
;enter with ax=key value.
;exit with si,cx -> the key's name in ASCII.
call prolog
mov di,offset help_buffer
test ah,ah ! jz $+5
jmp decode_specials ;decode special keys
;
cmp al,',' ! jne decode_key_LPar
mov call_si,offset Comma_key
mov call_cx,length Comma_key
jmp epilog
decode_key_LPar:
cmp al,'(' ! jne decode_key_RPar
mov call_si,offset LPar_key
mov call_cx,length LPar_key
jmp epilog
decode_key_RPar:
cmp al,')' ! jne decode_key_delete
mov call_si,offset RPar_key
mov call_cx,length RPar_key
jmp epilog
decode_key_delete:
mov si,di ;remember beginning
mov dl,al ! and dl,7fh ;form 7-bit code
cmp dl,7fh ! jne decode_non_delete ;jump if no <DEL> char
;
push si ! mov si,offset delete_string
mov cx,length delete_string
test al,80h ! jnz $+4
dec cx ! inc si ;skip 8-bit-indicator
push cx ! rep movsb ;move "Delete" string
mov al,0 ! stosb ;append terminator
pop call_cx ! pop call_si
jmp epilog
;
decode_non_delete:
cmp dl,32 ! jb decode_ctrl_key
mov call_si,si ;this is a normal displayable char
mov call_cx,1
stosw ! jmp epilog
;
decode_ctrl_key:
push si ! mov si,offset ctrl_string
mov cx,length ctrl_string
test ah,80h ! jnz $+4
dec cx ! inc si ;skip 8-bit-indicator
push cx ! rep movsb ;move "Ctrl"-char indicator
pop cx ! mov al,dl
add al,64 ! stosw ;put the control char
inc cx ! mov call_cx,cx
pop call_si ! jmp epilog
;
decode_specials:
cmp ah,csi ! jne decode_ss3
mov bx,offset csi_name_tab ;decode CSI controls
jmps decode_specials_1
decode_ss3:
cmp ah,ss3 ! jne decode_bin
mov bx,offset ss3_name_tab
decode_specials_1:
cmp al,[bx] ! je decode_specials_3
cmp byte ptr [bx],0
je decode_specials_3
add bl,1[bx] ! adc bh,0
inc bx ! inc bx ! jmps decode_specials_1
decode_specials_2:
mov bx,offset unknown_key_string
decode_specials_3:
mov cl,1[bx] ! lea si,2[bx]
decode_specials_4: xor ch,ch
mov call_cx,cx
mov call_si,si
jmp epilog
decode_bin:
cmp ah,'B' ! jne decode_specials_2
mov si,offset help_buffer
mov [si],al ! mov cl,1 ! jmps decode_specials_4
public ring_the_bell
ring_the_bell:
push bx ! push cx ! push dx
mov dl,7 ! ccpm c_rawio
xor cx,cx ! loop $
mov dl,7 ! ccpm c_rawio
pop dx ! pop cx ! pop bx ! ret
public position_cursor
position_cursor:
;enter with dh=col (0...131), dl=row (0..max_screen_line)
;exit with cursor set to that position.
call prolog
if v30
pushw offset epilog ;fall thru
else
mov ax,offset epilog ! push ax
endif
pos_cursor: std
mov di,offset cur_pos_string+7
xor ax,ax ! mov ah,dh ! inc ah
position_cursor_1: ;convert columne
or ah,ah ! jz position_cursor_2
if v30
shrw ax,8 ! div cb10
else
mov al,ah ! mov ah,0 ! div cb10
endif
xchg al,ah ! or al,'0' ! stosb
jmps position_cursor_1
position_cursor_2:
mov al,';' ! stosb ;put parameter delimiter
mov ah,dl ! inc ah
position_cursor_3: ;convert line number (row)
or ah,ah ! jz position_cursor_4
if v30
shrw ax,8 ! div cb10
else
mov al,ah ! mov ah,0 ! div cb10
endif
xchg al,ah ! or al,'0' ! stosb
jmps position_cursor_3
position_cursor_4:
mov byte ptr [di],csi ;insert control string introducer
mov dx,di ! ccpm c_writestr ;write out cursor position command
cld ! ret
cb10 db 10
public clear_to_eol
clear_to_eol:
;enter with dl=current row, dh=current column.
call prolog
call pos_cursor
clear_to_eol_1:
mov dx,offset clear_to_eol_string
ccpm c_writestr
jmp epilog
public clear_count
clear_count:
;enter with dl=current row, dh=current column, bl=column to clear to.
call prolog
call pos_cursor
mov cx,call_bx ! xor ch,ch
mov ax,call_dx ! xor ah,ah
sub cx,ax ! jb count_clear_2
count_clear_1:
push cx ! mov dl,' '
ccpm c_rawio
pop cx ! loop count_clear_1
mov dx,call_dx ! call pos_cursor
count_clear_2: jmp epilog
public chroutput
;normal terminal output routine.
;enter with al=character to print at the current cursor position
; ah=font to print in
;exit: cursor positioned after the printed char
chroutput:
call prolog
jmps xychrout_1
public xychrout
xychrout:
;enter with dh=col, dl=row, al=character to print, ah=font to print it in.
;exit: cursor positioned after the printed char
call prolog
call pos_cursor
xychrout_1:
mov ax,call_ax ;char to print
call set_font ;set font from AH --- preserves AX
cmp ah,0FFh ! je xychrout_specials
mov dx,ax ! and al,7fh
cmp al,20h ! jb xychrout_ctrl ;display control characters
ccpm c_write ! jmp epilog
xychrout_ctrl:
add al,40h ! test dl,80h
jz xychrout_ctrl1
add al,20h ! cmp al,07fh
jb xychrout_ctrl1
mov al,3ch
xychrout_ctrl1: mov ctrl_char,al
mov dx,offset ctrl_char_string
ccpm c_writestr ! jmp epilog
xychrout_specials:
mov bx,offset special_chars
cmp al,special_chars_lng
jbe $+4 ! mov al,0
xlat special_chars
mov dl,al ! ccpm c_write
jmp epilog
set_font: ;set character fonts
cmp ah,curr_font ! jne $+3 ! ret ;font already set
push ax ! mov dl,ah ;get selected font to dl
cmp dl,0FFh ! je set_font_special ;set special font
mov di,offset font_attribs
push ds ! pop es
rcr dl,1 ! jnc $+6
mov ax,'1;' ! stosw ;set bold
rcr dl,1 ! jnc $+6
mov ax,'4;' ! stosw ;set underline
rcr dl,1 ! jnc $+6
mov ax,'5;' ! stosw ;set blink
rcr dl,1 ! jnc $+6
mov ax,'7;' ! stosw ;set reverse
mov ax,'$m' ! stosw ;terminate string
mov dx,offset font_select_string
set_font_exit:
ccpm c_writestr ;select font
pop ax ! mov curr_font,ah
ret
set_font_special:
mov dx,offset special_font_string
jmps set_font_exit
public hardware_announce
;Enter with dl=row, dh=col for string to announce
;ds:si=string to announce, cx=string length
;Preserves the cursor position !
hardware_announce:
call prolog
mov word ptr temp,si ;save string offset
mov ax,call_ds
mov word ptr temp+2,ax ;save string segment
mov word ptr temp+4,cx ;save string length
mov ah,curr_font ! push ax ;save current font
mov dx,offset sv_cursor_string
ccpm c_writestr ;save the cursor position
mov dx,call_dx
call pos_cursor ;set new cursor position
cmp word ptr temp+4,0
jz hardware_announce_1
mov ah,9 ! call set_font ;set reverse video + bold
mov dx,offset temp
ccpm c_writeblk ;output string
mov cx,80 ! sub cx,call_cx
jbe hardware_announce_1
push cx ! mov dl,' '
ccpm c_write
pop cx ! loop $-8
hardware_announce_1:
mov dx,offset clear_to_eol_string
ccpm c_writestr ;clear to end of line
mov dx,offset rs_cursor_string
ccpm c_writestr ;restore cursor position
pop ax ! call set_font ;restore font
jmp epilog
public hardware_roll_down
hardware_roll_down:
;exit: if this machine is capable of hardware roll, do it and exit with cy=0,
; otherwise, exit with cy=1. The hardware roll must leave the last line
; on the screen as the last line.
;preserve bx.
call prolog
mov dx,offset roll_dn_string
jmps hw_roll_up
public hardware_roll_up
hardware_roll_up:
;exit: if this machine is capable of hardware roll, do it and exit with cy=0,
; otherwise, exit with cy=1. The hardware roll must leave the last line
; on the screen as the last line.
;preserve bx.
call prolog
mov dx,offset roll_up_string
hw_roll_up:
ccpm c_writestr
clc ! jmp epilog
public hardware_ins_line
hardware_ins_line:
;enter with al=line number where to insert the new line
call prolog
if v30
pushw offset ins_line_string
else
mov bx,offset ins_line_string ! push bx
endif
jmps hw_del_ins_line
public hardware_del_line
hardware_del_line:
;enter with al=line number to delete
call prolog
if v30
pushw offset del_line_string
else
mov bx,offset del_line_string ! push bx
endif
hw_del_ins_line:
xor dx,dx ! mov dl,al
call pos_cursor
pop dx ! ccpm c_writestr
jmp epilog
public block_cursor
block_cursor: stc ! ret
public underscore_cursor
underscore_cursor: stc ! ret
public set_screen_color
set_screen_color:
;enter with al=VT200 graphic rendition
; bit 0 All attributes off
; 1 Display bold
; 4 Display underlined
; 5 Display blinking
; 7 Display reverse
call prolog ! mov es,own_ds
mov di,offset help_buffer
xchg al,dl ! mov al,csi ! stosb ;build control string
mov ah,';' ! mov cl,0
set_screen_color_1:
rcr dl,1 ! jnc set_screen_color_2
mov al,cl ! and al,'0' ! stosw
inc cl ! cmp al,8 ! jb set_screen_color_1
set_screen_color_2:
mov ax,'$m' ! dec di ! stosw
mov dx,offset help_buffer ;write control string
ccpm c_writestr
jmp epilog
;code ends
end