; this is the console module ; modified 5-jul-83 to have console_owner in xios header ; modified 14-jun-83 to have key id's for escape sequence programming ; that start with 'A' cgroup group code,data ; use global equates nolist include ccpmxios.equ list public io_const ; function target public io_conin ; function target public io_conout ; function target public erase_screen ; used by ccpmxios init public crt_rfrsh public enable_cursor public disable_cursor public set_physical_cursor public video_status_line ; dw in this module public public_crt_init_attr public normal_const ; these routines are pointed public normal_conin ; to by offsets in the public co_no_escape ; screen structures public conin_shunt_stat public console_0_function_table public console_1_function_table public console_2_function_table public console_3_function_table if default_z19 public z19_special_char_tab public z19_special_func_tab public z19_esc_tab public z19_esc_func_tab endif ; default_z19 if default_oly public oly_special_char_tab public oly_special_func_tab public oly_esc_tab public oly_esc_func_tab endif ; default_oly extrn key_data:byte ; input byte from key int rtn extrn kbint_sw:byte extrn foreground_screen:byte ; externals from ccpmxios main extrn screen_struct_addrs:word ; externals from static area at 0c06h extrn nvcns:byte extrn console_owner:byte ; externals from graphics module extrn graphics_enable:near extrn graphics_disable:near ; externals from serial module extrn serial_input:near extrn serial_inp_stat:near extrn serial_output:near extrn poll:near extrn flagwait:near extrn flagset:near extrn io_statline:near ; ********************************************************* ; * * ; * FUNCTION KEY ASSIGNMENTS TO SCAN CODES * ; * 4/7/83 dwg * ; ********************************************************* prt equ dle ; control p for printer echo ; CONTROL'D FUNCTION KEYS F1C EQU 0D0H F2C EQU 0D1H F3C EQU 0D2H F4C EQU 0D3H F5C EQU 0D4H F6C EQU 0D5H F7C EQU 0D6H F8C EQU 0D7H F9C EQU 0D8H F10C EQU 0D9H F11C EQU 0DAH F12C EQU 0DBH PRTC EQU 0DCH eject ; CHARACTERS FROM KEYPAD WITH ALTERED ASCII VALUE K0 EQU '0' K1 EQU '1' K2 EQU '2' K3 EQU '3' K4 EQU '4' K5 EQU '5' K6 EQU '6' K7 EQU '7' K8 EQU '8' K9 EQU '9' KDSH EQU '-' KDOT EQU '.' kret equ cr ; keypad carriage return REDC EQU can ; AREN'T MNEMONICS WONDERFULL ; in order to implement the programmable function keys in the ; most efficient manner, the pf keys will generate contiguous ; key codes rel to pf_base and less than pf_len pf_base equ 0e8h ; base keycode for pf keys f1 equ pf_base f2 equ f1+1 f3 equ f2+1 f4 equ f3+1 f5 equ f4+1 f6 equ f5+1 f7 equ f6+1 f8 equ f7+1 f9 equ f8+1 f10 equ f9+1 f11 equ f10+1 f12 equ f11+1 lft equ f12+1 rght equ lft+1 ulft equ rght+1 upp equ ulft+1 dwn equ upp+1 pf_len equ dwn - pf_base ; screen switch characters console_0 equ f1c console_1 equ f2c console_2 equ f3c console_3 equ f4c eject ; ********************************************************* ; * * ; * HD46505S EQUATES OF INTEREST * ; * 6/8/83 dwg * ; ********************************************************* crt_base equ 06ch ; base addr of hd46505s crt_reg equ crt_base ; address register crt_data equ crt_base+2 ; data cursor_low equ 15 cursor_hi equ 14 crt_c_blue equ 08000h crt_c_green equ 0a000h crt_c_red equ 0c000h people_rfrsh equ 0e000h crt_chgarea equ 0e400h crt_clm equ 80 ; crt column size crt_row equ 24 ; crt row size ; video attribute byte has following structure: ; ; -- high nibble --- --- low nibble ---- ; 7 6 5 4 3 2 1 0 ; blink background bright foreground ; color color ; 7 6 5 4 3 2 1 0 ; | | | | | | | | ; | | | | | | | ----- unused ; | | | | | | --------- unused ; | | | | | ------------- unused ; | | | | | ; | | | | ----------------- underline ; | | | | ; | | | ------------------------ reverse ; | | | ; 0 0 1 ------------------------ brightness 1 (least bright) ; 0 1 0 ------------------------ brightness 2 ; 0 1 1 ------------------------ brightness 3 ; 1 0 0 ------------------------ brightness 4 ; 1 0 1 ------------------------ brightness 5 ; 1 1 0 ------------------------ brightness 6 ; 1 1 1 ------------------------ brightness 7 (brightest) hd46505_init_attr equ 0e0h hd46505_rev_attr equ 010h hd46505_under_attr equ 008h crt_init_attr equ hd46505_init_attr crt_br_shift_factor equ 512 crt_bright_1 equ 1 * crt_br_shift_factor crt_bright_2 equ 2 * crt_br_shift_factor crt_bright_3 equ 3 * crt_br_shift_factor crt_bright_4 equ 4 * crt_br_shift_factor crt_bright_5 equ 5 * crt_br_shift_factor crt_bright_6 equ 6 * crt_br_shift_factor crt_bright_7 equ 7 * crt_br_shift_factor ; ; equates for the olympia people keyboard hardware ; 4/7/83 dwg kbd_control equ 56h ; console stat kbd_data equ 54h ; console data kbd_rda equ 2 ; see rom doc eject ; about the console system: ; in order to allow the most flexible environment for both ; the developer and myself, the console system is designed to operate ; in several modes. Interrupts for the keyboard may be used or not ; depending on whether or not the kbint_sw byte is zero or non-zero ; at xios init time. ; the console input functions now use the same state machine approach ; as the escape sequence handler in the conout routines ; this is to allow the clean implementation of the function keys (pf) ; the screen structure contains the offset of the next conin, const handler ; for any particular console. eject cseg ; ********************************************************* ; * CONSOLE STATUS ROUTINE * ; ********************************************************* io_const: ; exit: AL = 0ffh if ready ; AL = 0 if not ; ALL SEGMENT REGISTERS PRESERVED: ; CS,DS,ES,SS must be preserved though call cmp dl,nvcns ! jb cs_ok ret ; no serial support needed here PUBLIC CS_OK cs_ok: mov dl,console_owner xor dh,dh mov bx,dx shl bx,1 mov bx,screen_struct_addrs[bx] jmp ss_const[bx] PUBLIC NORMAL_CONST normal_const: ; now, do we have any pfk work to do? ; lets fetch the working offset and see if anything is going on mov si,ss_pfk_offset[bx] and si,si jz no_pfk_activity mov al,byte ptr[si] ; fetch next pfk byte and al,al jz no_pfk_activity ; pf table has non-zero byte ; return active status mov al,0ffh ; always ready when pfk activity ret ; pfk in progress PUBLIC NO_PFK_ACTIVITY no_pfk_activity: ; allow a faster determination next time mov ax,0 ! mov ss_pfk_offset[bx],ax ; normal processing if not pf key mov al,kbint_sw ; get keyboard mode byte and al,al ; set condition codes jz poll_kst ; mov al,0ffh ; always ready for int status PUBLIC IOC_RET ioc_ret: ret PUBLIC POLL_KST poll_kst: in al,kbd_control ; get keyboard uart status test al,kbd_rda ; test for receive data available mov ax,0 ; retcode=0 jz notrdy dec ax ; retcode = ffff PUBLIC NOTRDY notrdy: and ax,ax ; set condition codes jmps ioc_ret ; use return above EJECT ; ********************************************************* ; * CONSOLE INPUT ROUTINE * ; ********************************************************* io_conin: cmp dl,nvcns ! jb ci_ok mov al,0 ! ret ; who cares PUBLIC CI_OK ci_ok: mov dl,console_owner xor dh,dh ; console # < 256 only mov bx,dx ; bx = console # (word) shl bx,1 ; mov bx,screen_struct_addrs[bx] jmp ss_conin[bx] normal_conin: ; any pfk activity? mov si,ss_pfk_offset[bx] and si,si jz not_pfk ; no pfk activity PUBLIC CONIN_PFK_ACTIVITY conin_pfk_activity: ; get next pf byte xor ah,ah mov al,byte ptr [si] ; current byte and al,al ; value pf byte? jz pfk_done ; not pfk ; it was valid, bump the ptr for next time inc si ; ptr to next byte mov ss_pfk_offset[bx],si jmps conin_done ; use common exit rtn pfk_done: mov ss_shunt[bx],al ; release resource jmps not_pfk ;******************************************************* ; this routine runs if conin is entered and no pfkey ; work is in progress(normal conin function) PUBLIC NOT_PFK not_pfk: ; allow a faster determination next time mov ax,0 ! mov ss_pfk_offset[bx],ax mov al,kbint_sw ! and al,al jz coninp ; this is the interrupt driven status routine push cx ; save cx for caller mov dx,key_flag ; flagwait needs the flag number push bx ; save ss ptr call flagwait ; give up until key is pressed pop bx ; restore ss ptr pop cx ; restore cx for caller jmps conin_doit ; character waiting.... ;********************************************************** ; this is the polled status routine PUBLIC CONINP coninp: mov dl,const_poll_no push bx ; save ss ptr call poll pop bx ; restore ss ptr jmps conin_doit ;********************************************************** PUBLIC CONIN_DOIT conin_doit: mov al,kbint_sw and al,al jz conin_doit_non_int PUBLIC CONIN_DOIT_INT conin_doit_int: mov al,key_data ; get char from int rtn buffer jmps conin_doit_common PUBLIC CONIN_DOIT_NON_INT conin_doit_non_int: in al,kbd_data ; get char from keyboard uart jmps conin_doit_common PUBLIC CONIN_DOIT_COMMON conin_doit_common: xor ah,ah ; zap ho byte because push bx ; save ss ptr mov bx,offset key_xlat_tab xlat al ; use my table pop bx ; restore ss ptr call switch_check ; test for screen switch request call pfk_check ; hook for pf keys PUBLIC CONIN_DONE conin_done: ret ; return to caller ;***************************************************************** PUBLIC SWITCH_CHECK switch_check: cmp al,console_0 ! jz to_console_0 cmp al,console_1 ! jz to_console_1 cmp al,console_2 ! jz to_console_2 cmp al,console_3 ! jz to_console_3 ret PUBLIC TO_CONSOLE_0,TO_CONSOLE_1,TO_CONSOLE_2,TO_CONSOLE_3 to_console_0: mov ax,0ff00h ! mov console_owner,al ! ret to_console_1: mov ax,0ff01h ! mov console_owner,al ! ret to_console_2: mov ax,0ff02h ! mov console_owner,al ! ret to_console_3: mov ax,0ff03h ! mov console_owner,al ! ret eject ; the function of this routine is to test the input character ; to see if it is a pf key. this is possible because the pf ; keys translate into contiguous numbers => pf_base PUBLIC PFK_CHECK pfk_check: cmp al,pf_base ! jnb pfk_ok ret PUBLIC PFK_OK pfk_ok: ; at this point, we have in al an ascii value between ; pf_base and pf_base+pf_len ; if we subtract the pf_base we will have a 0 rel ; number of the pf key struck. sub al,pf_base ; now we need to calculate the offset of the beginning of the ; pfk table entry in the screen structure ; make entire ax valid pfk number xor ah,ah ; move length of entry to cx mov cx,pfk_entry_length + 3 ; calculate beginning entry mul cx ; adjust for start of table add ax,ss_pfk_base[bx] ; adjust past keyid, count add ax,2 ; at this point we know what we want to do but there may ; already be a shunt in operation, therefore in order to ; assure we will not have a resource conflict, a call is ; made to the rtm poll system to acquire the shunt for ; a particular virtual console(screen structure) push ax ; save new pfk_base on stack mov dl,conin_shunt_poll_no ; poll number for shunt push bx ; save bx for me call poll ; don't return till I have shunt pop bx ; restore bx for me pop ax ; restore new pfk_base from stack ; now ax should have offset into pfk table for specific pfk mov ss_pfk_offset[bx],ax ; now screen structure has offset of 1st pf character pop ax ; oh!! am i ashamed jmp normal_conin EJECT ; ********************************************************* ; * CONSOLE OUTPUT ROUTINE W/ESCAPE SEQUENCES * ; ********************************************************* io_conout: cmp dl,nvcns ! jb co_ok ret co_ok: ; if we are here, we need to do virtual console output mov al,cl mov ah,dl ;AH = virtual console # xor dh,dh ;get screen structure for mov bx,dx ;this console shl bx,1 ;word index mov bx,screen_struct_addrs[bx] jmp ss_escape[bx] ;escape handler if in the middle ;of and escape sequence else ;jump to CO_NO_ESCAPE eject ; the following code is experimental and deals with ; programming the function keys using an escape sequence co_function: ; colon means function def coming mov ax,offset co_fkey_id ; next get key id mov ss_escape[bx],ax ; modify state variable ret ; return to caller co_fkey_id: ; calculate the offset into the screen structure for the coming ; bytes xor ah,ah ; make byte in al 16 bits and al,07fh ; no high order bit on fid sub al,'A' ; A=Fn0 B=Fn1 C=Fn2 ... mov cx,pfk_entry_length + 3 ; size per function key in table mul cx ; calc offset into table add ax,ss_pfk_base[bx] ; adjust for start of table add ax,2 ; adjust past keyid, count ; before we start messing with the console's screen structure ; it is a good idea to own the shunt push ax ; save ax for me mov dl,conin_shunt_poll_no ; poll number for shunt push bx ; save bx for me call poll ; don't return till I have shunt pop bx ; restore bx for me pop ax ; restore ax for me ; place offset where bytes will go into the screen structure mov ss_fpgm_off[bx],ax ; set max length for safety mov al,pfk_entry_length mov ss_fpgm_count[bx],al ; next we will accept bytes mov ax,offset co_fkey_byte mov ss_escape[bx],ax ret ; return to caller co_fkey_byte: cmp al,0 ; end of string? jne co_fkey_not_zero ; if not end, go around mov cl,1 mov ss_fpgm_count[bx],cl co_fkey_not_zero: ; now we have a valid byte in the al ; store the byte in the appropriate byte of the function string mov di,ss_fpgm_off[bx] ; get appropriate offset mov byte ptr[di],al ; save the byte where appropriate ; now lets increment the offset mov al,ss_fpgm_count[bx] sub al,1 mov ss_fpgm_count[bx],al jz no_more_bytes ; if zero, no more possible. ; revert to normal processing ; not last one, orderly processing continues ; increment the offset for next time mov ax,ss_fpgm_off[bx] ; fetch current value inc ax ; bump it mov ss_fpgm_off[bx],ax ; put it back ret ; return to caller no_more_bytes: mov ax,offset co_no_escape ; offset of normal handler mov ss_escape[bx],ax ; place where it will no the most good ret ; return to caller eject ; the purpose of the following code is to allow an application program ; to query the function keys of a particular console ; in order to query a function key it is necessary to emit ; an escape sequence as follows: ; ; ; ; ; the xios will then return through conin the following data: ; ; ... ; function_query: mov ax,offset fq_fkey_id mov ss_escape[bx],ax ret fq_fkey_id: ; calculate offset into function table for appropriate console xor ah,ah and al,07fh sub al,'A' mov cx,pfk_entry_length+3 mul cx add ax,ss_pfk_base[bx] mov si,ax add si,2 mov cx,0 public count_loop count_loop: cmp byte ptr [si],0 jz no_more_valid_bytes inc cx inc si jmps count_loop public no_more_valid_bytes no_more_valid_bytes: mov si,ax ! inc si add cl,'A' mov byte ptr [si],al mov ss_pfk_offset[bx],ax mov ax,offset co_no_escape mov ss_escape[bx],ax ; now here comes the tricky part. kick off the key flag ; so as to start the internal reader. push ax ! push bx ! push cx ! push dx push si ! push di ! push bp mov dx,key_flag call flagset pop bp ! pop di ! pop si pop dx ! pop cx ! pop bx ! pop ax ret ;;;;;;;;;;;;;;;;; eject co_no_escape: ;look for CR,LF,backspace,ESC mov di,ss_sp_ch_tab[bx] mov si,ss_sp_fn_tab[bx] call co_look_up jcxz co_simple_char ret ;all done if special handling ;or expanding and escape ;sequence co_simple_char: ;simple character output ; Put character in screen and update cursor position ; BX = screen structure ; AL = character ;********************************************************************* no_bell: mov di,ss_cursor[bx] ;cursor byte offset push es call set_up_es co_back: push ax ;save virtual console number mov ah,ss_attribute[bx] stosw ;update data and atrribute pop ax pop es ;DI points at next data ;and attribute word cmp ss_column[bx],columns_per_screen-1 jb inc_col test ss_mode[bx],ssm_no_wrap jnz co_nowrap call carriage_return jmp line_feed co_nowrap: ret ;don't move cursor ;when at end of line inc_col: jmp r_right ;move cursor right ; eject co_look_up: ; entry: BX = address of screen structure ; AH = device# ; AL = character to scan for ; DI = ptr to lookup table, first byte is length ; SI = table of functions to jump to if char found in ; lookup table ; exit: CX = 0ffffh if special character found ; and special function has been performed ; CX = 0 if char not found, no special handling is performed ; AX,BX preserved if not special function mov bp,es ! mov dx,ds ;use registers instead of mov es,dx ;stack for speed xor cx,cx ! mov cl,[di] ;length of lookup mov dx,cx ;save the length inc di repne scasb ;is it in table ? mov es,bp ;restore UDA je lu_func ;CX=0 if not found ret lu_func: inc cx ;iteration we matched on sub dx,cx ;function number shl dx,1 ;jump to special function add si,dx call word ptr [si] xor cx,cx ! dec cx ;return CX=0FFFFH ret eject ; use olympia escape sequences oly_mode: mov ax,offset oly_special_char_tab ! mov ss_sp_ch_tab[bx],ax mov ax,offset oly_special_func_tab ! mov ss_sp_fn_tab[bx],ax mov ax,offset oly_esc_tab ! mov ss_esc_tab[bx],ax mov ax,offset oly_esc_func_tab ! mov ss_escfun_tab[bx],ax ret ; use z19 escape sequences z19_mode: mov ax,offset z19_special_char_tab ! mov ss_sp_ch_tab[bx],ax mov ax,offset z19_special_func_tab ! mov ss_sp_fn_tab[bx],ax mov ax,offset z19_esc_tab ! mov ss_esc_tab[bx],ax mov ax,offset z19_esc_func_tab ! mov ss_escfun_tab[bx],ax ret ; ; Olympia "PEOPLE" specific attribute handler per Olympia Spec. ; attrib: mov ss_escape[bx],offset attrib_char ret attrib_char: or al,80h and al,0f8h ; per bios13 mov ss_attribute[bx],al ; set attrib mov ss_escape[bx],offset co_no_escape ret eject ; ********************************************************* ; * X AND Y * ; * oly xy is backwards * ; ********************************************************* olyxy: mov ss_escape[bx],offset olyxy_col ;wait for col ret olyxy_col: sub al,32 ;make col relative to 0 cmp al,columns_per_screen-1 jbe olycol_ok mov ss_escape[bx],offset olyxy_err olycol_ok: mov ss_column[bx],al mov ss_escape[bx],offset olyxy_row ;wait for row ret olyxy_row: sub al,32 ;make row relative to 0 cmp al,rows_per_screen-1 jbe olyxy_set_row mov al,rows_per_screen-1 olyxy_set_row: mov ss_row[bx],al call compute_cursor call set_physical_cursor olyxy_err: mov ss_escape[bx],offset co_no_escape ret eject ;************************************************************************ ;* * ;* SPECIAL CHARACTER FUNCTIONS AND ESCAPE SEQUENCE HANDLERS * ;* * ;************************************************************************ ; ********************************************************* ; * CARRIAGE RETURN * ; ********************************************************* carriage_return: xor dx,dx xchg ss_column[bx],dl ;set column to 0 shl dx,1 ;back up cursor sub ss_cursor[bx],dx cr_done: jmp set_physical_cursor ; ********************************************************* ; * LINE FEED * ; ********************************************************* line_feed: cmp ss_row[bx],rows_per_screen-1 je lf_scroll jmp d_down ;no-just move cursor down lf_scroll: ;yes-scroll screen up xor dl,dl ;start row mov dh,rows_per_screen-1 ;end row call scroll_up jmp erase_line ; ********************************************************* ; * BACK SPACE * ; ********************************************************* back_space: mov di,ss_cursor[bx] test di,di ;at home position, return jz bs_ret cmp ss_column[bx],0 ;if column 0, go up to previous line je bs_row dec ss_column[bx] jmps bs_set_cursor bs_row: dec ss_row[bx] mov ss_column[bx],columns_per_screen - 1 bs_set_cursor: sub di,2 mov ss_cursor[bx],di jmp set_physical_cursor bs_ret: ret ; ********************************************************* ; * ESCAPE * ; ********************************************************* escape: ;expand escape sequences mov ss_escape[bx],offset escape1 ret ;back to co_look_up escape1: ;first char of escape sequence mov ss_escape[bx],offset co_no_escape ;assume done with escape mov di,ss_esc_tab[bx] ; use screen structure offset mov si,ss_escfun_tab[bx] ; use screen structure offset jmp co_look_up ;escape field is set by the ;handler - see X_AND_Y: ; ********************************************************* ; * ERASE SCREEN * ; ********************************************************* erase_screen: ;ESC E push ax ; ( ax --- ) push es ; ( ax es --- ) call set_up_es ; set es to regen buffer mov cx,screen_siz ; for all screen words xor di,di ; di = 0 mov ah,crt_init_attr ; use initial attribute mov al,' ' ; clear to space rep stosw ; do the real job pop es ; ( ax --- ) pop ax ; ( --- ) ;jmps home ; ; ********************************************************* ; * HOME * ; ********************************************************* home: ; ESC H xor dx,dx ; dx = 0 mov ss_cursor[bx],dx ; cursor = 0 mov ss_row[bx],dl ; row = 0 mov ss_column[bx],dl ; column = 0 jmp set_physical_cursor ; as below so above ; ********************************************************* ; * RIGHT * ; ********************************************************* right: ;ESC C cmp ss_column[bx],columns_per_screen-1 jb r_right ret r_right:add ss_cursor[bx],2 inc ss_column[bx] jmp set_physical_cursor ; ********************************************************* ; * LEFT * ; ********************************************************* left: ;ESC D cmp ss_column[bx],0 ja l_left ret l_left: sub ss_cursor[bx],2 dec ss_column[bx] jmp set_physical_cursor ; ********************************************************* ; * DOWN * ; ********************************************************* down: ;ESC B cmp ss_row[bx],rows_per_screen-1 jb d_down ret d_down: add ss_cursor[bx],columns_per_screen*2 inc ss_row[bx] jmp set_physical_cursor ; ********************************************************* ; * UP * ; ********************************************************* up: ;ESC A cmp ss_row[bx],0 ja d_up ret d_up: sub ss_cursor[bx],columns_per_screen*2 dec ss_row[bx] jmp set_physical_cursor ; ********************************************************* ; * UP WITH SCROLL * ; ********************************************************* up_with_scroll: ;ESC I cmp ss_row[bx],0 ;if not the top line ja up ;just do a cursor up xor dl,dl ;start row mov dh,rows_per_screen-1 ;ending row call scroll_down ;down one row call erase_line ;blank out current row ret ;don't move the cursor ; ********************************************************* ; * REPORT * ; ********************************************************* report: ret ; ********************************************************* ; * SAVE * ; ********************************************************* save: ;ESC j mov ax,ss_xy[bx] ; get cursor coords in ax mov ss_oldxy[bx],ax ; save in ss_old_xy mov ax,ss_cursor[bx] ; get cursor offset into regen mov ss_oldcursor[bx],ax ; save in ss_oldcursor ret ; return to caller ; ********************************************************* ; * RESTORE * ; ********************************************************* restore: ;ESC k mov cx,ss_oldxy[bx] ; get olf cursor coords mov ss_xy[bx],cx ; place in cursor slot mov cx,ss_oldcursor[bx] ; get old offset mov ss_cursor[bx],cx ; place in current offset jmp set_physical_cursor ; as below so above ; ********************************************************* ; * X AND Y * ; ********************************************************* x_and_y: ;ESC Y mov ss_escape[bx],offset xy_row ;wait for row ret xy_row: sub al,32 ;make row relative to 0 cmp al,rows_per_screen-1 jbe row_ok mov ss_escape[bx],offset xy_err row_ok: mov ss_row[bx],al mov ss_escape[bx],offset xy_col ;wait for column ret xy_col: sub al,32 ;make column relative to 0 cmp al,columns_per_screen-1 jbe xy_set_col mov al,columns_per_screen-1 xy_set_col: mov ss_column[bx],al call compute_cursor call set_physical_cursor xy_err: mov ss_escape[bx],offset co_no_escape ret ; ********************************************************* ; * ERASE BEGIN * ; ********************************************************* ; AH = virtual screen number erase_begin: ;ESC b push es ; save es for caller call set_up_es ; point es at regen buffer mov ax,ss_cursor[bx] ;cursor byte offset shr ax,1 ;make word offset inc ax ;make relative to 1 mov cx,ax ;number of words to erase mov ah,crt_init_attr ; use initial attribute mov al,' ' ; use a space xor di,di ;start at beginning rep stosw ;of display pop es ; restore es for caller ret ; return to caller ; ********************************************************* ; * ERASE END * ; ********************************************************* erase_end: ;ESC j push es call set_up_es mov ax,ss_cursor[bx] ;cursor byte offset mov di,ax ;starting offset to erase shr ax,1 ;make word offset mov cx,screen_siz ;screen size in words sub cx,ax ;less 0 relative cursor position mov ah,crt_init_attr ; use initial attribute mov al,' ' ; use a space rep stosw ; do actual dirty deed pop es ; restore es for caller ret ; return to caller ; ********************************************************* ; * ERASE LINE * ; ********************************************************* erase_line: ;ESC l push es ; save es for caller call set_up_es ; point es at regen buffer xor ax,ax mov al,ss_row[bx] ;current row mov cx,columns_per_screen ;words to move mul cx ;word offset of current row shl ax,1 ;byte offset mov di,ax ;destination MOV AL,' ' MOV AH,CRT_INIT_ATTR rep stosw ; do the actual dirty deed pop es ; restore es for caller ret ; return to caller ; ********************************************************* ; * ERASE BEGINNING OF LINE * ; ********************************************************* erase_bol: ;ESC o push es ; save es for caller call set_up_es ; point es at virtual screen xor ax,ax mov al,ss_row[bx] ;current row mov cx,columns_per_screen*2 mul cx ;byte offset of row mov di,ax xor cx,cx mov cl,ss_column[bx] ;words to blank inc cx ;include cursor mov ah,crt_init_attr ; use initial attribute mov al,' ' ; use a space rep stosw ; do the actual dirty deed pop es ; restore es for caller ret ; return to caller ; ********************************************************* ; * ERASE END OF LINE * ; ********************************************************* erase_eol: ;ESC K push es call set_up_es mov di,ss_cursor[bx] mov cx,columns_per_screen ; for column/line sub cl,ss_column[bx] ; minus current columns mov ah,crt_init_attr ; use initial attribute mov al,' ' ; use a space rep stosw ; do the actual dirty deed pop es ; restore es for caller ret ; return to caller ; ********************************************************* ; * INSERT LINE * ; ********************************************************* insert_line: ;ESC L push ax ;save virtual console number mov dl,ss_row[bx] ;start row mov dh,rows_per_screen-1 ;ending row call scroll_down ;move screen down one row call erase_line ;blank out the line xor ax,ax ;save virtual console number xchg al,ss_column[bx] ;set cursor to beginning shl ax,1 ;of line sub ss_cursor[bx],ax pop ax jmp set_physical_cursor ; ********************************************************* ; * DELETE LINE * ; ********************************************************* delete_line: ;ESC M push ax ;save virtual console number mov dl,ss_row[bx] ;move screen up one line mov dh,rows_per_screen-1 ;to present row call scroll_up push ss_xy[bx] ;save row and column mov ss_row[bx],rows_per_screen-1 call erase_line ;erase last line pop ss_xy[bx] ;restore row and column pop ax ;restore virtual console number jmp carriage_return ;put cursor at beginning of line ; ********************************************************* ; * DELETE CHARACTER * ; ********************************************************* delete_char: ;ESC N push es ; ( es --- ) call set_up_es mov di,ss_cursor[bx] mov si,di add si,2 xor cx,cx mov cl,columns_per_screen-1 sub cl,ss_column[bx] push ds ; ( es ds --- ) push es ; ( es ds es --- ) pop ds ; ( es ds --- ) rep movsw mov ah,crt_init_attr mov al,' ' mov 0[di],ax pop ds ; ( es --- ) pop es ; ( --- ) ret ; ********************************************************* ; * ENTER REVERSE * ; ********************************************************* enter_reverse: ;ESC p test ss_mode[bx],ssm_reverse ;already in reverse video ? jnz rev_done or ss_mode[bx],ssm_reverse ;turn on reverse video mode bit ;jmps rev_swap rev_swap: mov al,ss_attribute[bx] mov ah,al ;save blink and bright bits and al,077h ;mask off blink and bright bits mov cl,4 ror al,cl ;swap nibbles and colors and ah,088h ;get just the blink and bright bits or al,ah ;put them together again mov ss_attribute[bx],al ;save the new attribute rev_done: ret ; ********************************************************* ; * EXIT REVERSE * ; ********************************************************* exit_reverse: ;ESC q test ss_mode[bx],ssm_reverse jz rev_done and ss_mode[bx],not ssm_reverse ;turn off reverse mode bit jmps rev_swap ; ********************************************************* ; * ENTER BLINK * ; ********************************************************* enter_blink: ;ESC s or ss_attribute[bx],080h ret exit_blink: ;ESC t and ss_attribute[bx],not (080h) ret enter_bright: ;ESC r or ss_attribute[bx],08h ret exit_bright: ;ESC u and ss_attribute[bx],not (08h) ret enable_cursor: ;ESC e jmps cursor_on_off ; ********************************************************* ; * DISABLE CURSOR * ; ********************************************************* disable_cursor: ;ESC f cursor_on_off: ret ; ********************************************************* ; * ENABLE WRAP * ; ********************************************************* enable_wrap: ;ESC v and ss_mode[bx],not ssm_no_wrap jmp io_statline disable_wrap: ;ESC w or ss_mode[bx],ssm_no_wrap jmp io_statline eject ;************************************************************************ ;* * ;* UTILITY ROUTINES FOR CONSOLE OUTPUT * ;* * ;************************************************************************ scroll_up: ;scroll up in range given in ;--------- ;DX ; entry: AH = virtual console number ; BX = screen structure ; DL = start row, 0 relative ; DH = ending row, 0 relative ; exit: AX,BX,ES preserved push ax ! push es call set_up_es mov cx,dx ;copy of start,ending rows xor ax,ax ;set up SI,DI mov al,dl ;AX = beginning row mov dx,columns_per_screen*2 mul dx ;byte offset of beginning row mov di,ax ;first destination word add ax,columns_per_screen*2 ;first word to copy mov si,ax ;set up CX mov ax,cx ;AL=start,AH=end sub ah,al ;end always > start xor al,al xchg al,ah ;AX=number or rows to move mov dx,columns_per_screen mul dx ;words to move up mov cx,ax ;get count push ds ! push es ! pop ds rep movsw pop ds ! pop es ! pop ax ret eject scroll_down: ;scroll down in range given ;----------- ;in DX ; entry: AH = virtual console number ; BX = screen structure ; DL = start row, 0 relative ; DH = ending row, 0 relative ; exit: AX,BX,ES preserved push ax ! push es call set_up_es mov cx,dx ;copy of start,ending rows ;set up SI,DI xor ax,ax mov al,dh ;AX=ending row inc al ;next row after end row mov dx,columns_per_screen*2 mul dx ;byte offset of next row sub ax,2 ;last word of ending row mov di,ax ;first destination word sub ax,columns_per_screen*2 ;first word to copy mov si,ax std ;auto-decrement SI,DI ;set up CX mov ax,cx ;AL=start,AH=ending sub ah,al ;end always > start xor al,al xchg al,ah ;# rows to move mov dx,columns_per_screen mul dx ;words to move down mov cx,ax ;get count push ds ! push es ! pop ds rep movsw pop ds ! pop es ! pop ax cld ;zero direction flag ! ret eject compute_cursor: ;update ss_cursor field from ;-------------- ;ss_row and ss_column fields ; entry: BX = screen structure address ; AH = virtual console device # ; ES = segment of video ; exit: CX,DX used ; AX,BX preserved push ax ;save virtual console number xor ax,ax mov al,ss_row[bx] ;row and column mov cx,columns_per_screen*2 mul cx xor cx,cx mov cl,ss_column[bx] shl cx,1 add ax,cx mov ss_cursor[bx],ax ;word offset in screen array pop ax ;restore virtual console number ret eject ; ********************************************************* ; * * ; * SET PHYSICAL CURSOR * ; * * ; ********************************************************* set_physical_cursor: ; If the screen is the foreground screen then set the ; cursor register in the CRT CONTROLLER to ss_cursor[bx] ; ; entry: BX = screen structure address ; AH = virtual console device # ; ES = segment of video ; exit: AX,CX,DX used cmp ah,foreground_screen jne sp_ret mov cx,ss_cursor[bx] ;byte offset of cursor shr cx,1 ;make a word value mov dx,crt_reg ; use people video mov al,cursor_low ;register to update out dx,al mov dx,crt_data mov al,cl out dx,al mov dx,crt_reg mov al,cursor_hi out dx,al mov al,ch mov dx,crt_data out dx,al sp_ret: ret eject ; ********************************************************* ; * * ; * SET UP EXTRA SEGMENT FOR ACCESS TO REGEN * ; * * ; ********************************************************* set_up_es: ;set up ES for subsequent ; entry: BX = screen structure ; AH = virtual console number ; exit: ES = physical video RAM segment if ; foreground, else ES = ; virtual console RAM for this screen ; CX = destroyed mov cx,crt_rfrsh ; dwg 3/19/83 mov es,cx cmp ah,foreground_screen je set_r mov cx,ss_screen_seg[bx] mov es,cx set_r: ret eject ; ; console shunt (internal reader) status routine and ; serially reuseable resource guard ; conin_shunt_stat: mov al,0ffh mov dl,console_owner xor dh,dh mov bx,dx shl bx,1 mov bx,screen_struct_addrs[bx] xchg ss_shunt[bx],al not al ret eject dseg ; ********************************************************* ; * * ; * KEY SCAN CODE TRANSLATION TABLE * ; * * ; ********************************************************* ; the olympia keyboard is interfaced using a uart and in many cases ; already passes back ascii to the processor, BUT... in some cases ; translation is necessary. The keypad numbers are an example of this. ; in order to process the pf keys in the most efficient manner, all ; of the keys that will be processed as pf keys have translation table ; entries that give them contiguous ascii values ranging from ; pf_base to pf_base+pf_len ( see the equates above ) ; since 0e8h through 0ffh are not currently assigned by olympia, ; these ascii values will be used for the pf keys. since they ; are used for this purpose, they have been marked as pfk in the ; table to remind you that pf_base is set for 0e8h pfk equ 13h ; pfk means ascii code allocated to pf keys open equ 69h ; open means ascii code available for assignment eject key_xlat_tab: ; 00h+ 0/8 1/9 2/a 3/b 4/c 5/d 6/e 7/f x00 db nul, soh, stx, etx, eott, enq, ack, bel x08 db bs, ht, lf, vt, ff, cr, so, shi x10 db dle, dc1, dc2, dc3, dc4, nak, syn, etb x18 db can, em, subb, esc, fs, gs, rds, us x20 db ' ', '!', '"', '#', '$', '%', '&', 27h x28 db '(', ')', '*', '+', ',', '-', '.', '/' x30 db '0', '1', '2', '3', '4', '5', '6', '7' x38 db '8', '9', ':', ';', '<', '=', '>', '?' x40 db '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G' x48 db 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O' x50 db 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W' x58 db 'X', 'Y', 'Z', '[', '\', ']', '^', '_' x60 db open, 'a', 'b', 'c', 'd', 'e', 'f', 'g' x68 db 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o' x70 db 'p', 'q', 'r', 's', 't', 'u', 'v', 'w' x78 db 'x', 'y', 'z', '{', '|', '}', '~', 7fh eject ; 80h+ 0/8 1/9 2/a 3/b 4/c 5/d 6/e 7/f x80 db open, upp, dwn, rght, lft, ulft, open, open x88 db open, open, open, open, open, open, open, open x90 db F1, F2, F3, F4, F5, F6, F7, F8 x98 db F9, F10, F11, F12, PRT, open, open, open xa0 db bs, ht, cr, REDC, esc, ' ', DEL, KRET xa8 db open, open, open, open, open, KDSH, KDOT, open xb0 db K0, K1, K2, K3, K4, K5, K6, K7 xb8 db K8, K9, open, open, open, open, open, open xc0 db open, open, open, open, open, open, open, open xc8 db open, open, open, open, open, open, open, open xd0 db F1C, F2C, F3C, F4C, F5C, F6C, F7C, F8C xd8 db F9C, F10C, F11C, F12C, PRTC, open, open, open xe0 db open, open, open, open, open, open, open, open xe8 db pfk, pfk, pfk, pfk, pfk, pfk, pfk, pfk xf0 db pfk, pfk, pfk, pfk, pfk, pfk, pfk, pfk xf8 db pfk, pfk, pfk, pfk, pfk, pfk, pfk, pfk EJECT ;************************************************************************ ;* SPECIAL KEY SCAN AND FUNCTION TABLES * ;* for olympia escape sequences * ;************************************************************************ oly_special_char_tab db 5 ;number of special chars db cr,lf,bs,esc,ff ;the special chars oly_special_func_tab dw carriage_return ;the special char routines dw line_feed dw back_space dw escape dw erase_screen oly_esc_tab db 12 ;number of escape sequences ;supported db 'f' ; set cursor position db 'g' ; set attribute db 'J' ; erase to end of screen db 'K' ; erase to end of line db 'L' ; insert line db 'M' ; delete line db 'Z' ; z-19 mode db 'O' ; oly mode db ':' ; function key programming char db ';' ; function key query char db 'F' ; enter graphics db 'G' ; exit graphics oly_esc_func_tab: dw olyxy ; f - set cursor position dw attrib ; g - set attribute dw erase_end ; J - erase end of screen dw erase_eol ; K - erase end of line dw insert_line ; L - insert line dw delete_line ; M - delete line dw z19_mode ; Z - z-19 mode dw oly_mode ; O - oly mode(just in case) dw co_function ; : - function key set dw function_query ; ; - function key query dw graphics_enable ; F - enter graphics mode dw graphics_disable; G - exit graphics mode EJECT ;************************************************************************ ;* SPECIAL KEY SCAN AND FUNCTION TABLES * ;* for z19 escape sequences * ;************************************************************************ z19_special_char_tab db 4 ;number of special chars db cr,lf,bs,esc ;the special chars z19_special_func_tab dw carriage_return ;the special char routines dw line_feed dw back_space dw escape z19_esc_tab db 34 ;number of escape sequences db 'H','C','D','B','A' ;the second char db 'I','j','k','Y','E' ;in the escape db 'b','J','l','o','K' ;sequence db 'L','M','N','p','q' db 'r','u','s','t','e' db 'f','v','w' db 'O','Z',':',';','F','G' z19_esc_func_tab: dw home ;H dw right ;C dw left ;D dw down ;B dw up ;A dw up_with_scroll ;I dw save ;j dw restore ;k dw x_and_y ;Y - row and column dw erase_screen ;E dw erase_begin ;b dw erase_end ;J dw erase_line ;l dw erase_bol ;o - BOL = begin of line dw erase_eol ;K - EOL = end of line dw insert_line ;L dw delete_line ;M dw delete_char ;N dw enter_reverse ;p dw exit_reverse ;q dw enter_bright ;r dw exit_bright ;u dw enter_blink ;s dw exit_blink ;t dw enable_cursor ;e dw disable_cursor ;f dw enable_wrap ;v dw disable_wrap ;w dw oly_mode ;O dw z19_mode ;Z dw co_function ;: dw function_query ;; dw graphics_enable ;F dw graphics_disable;G ; end of z19 escape data video_status_line dw screen_siz * 2 public_crt_init_attr db hd46505_init_attr crt_rfrsh dw people_rfrsh eject console_0_function_table: db f1 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f2 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f3 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f4 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f5 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f6 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f7 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f8 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f9 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f10 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f11 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f12 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db lft ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db rght ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db ulft ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db upp ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db dwn ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator eject console_1_function_table: db f1 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f2 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f3 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f4 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f5 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f6 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f7 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f8 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f9 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f10 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f11 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f12 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db lft ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db rght ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db ulft ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db upp ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db dwn ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator eject console_2_function_table: db f1 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f2 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f3 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f4 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f5 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f6 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f7 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f8 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f9 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f10 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f11 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f12 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db lft ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db rght ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db ulft ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db upp ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db dwn ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator eject console_3_function_table: db f1 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f2 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f3 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f4 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f5 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f6 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f7 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f8 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f9 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f10 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f11 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db f12 ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db lft ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db rght ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db ulft ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db upp ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator db dwn ; pf key id byte db 0 ; active count rb pfk_entry_length ; string space db 0 ; zero byte terminator ; end of console module