; =====> ZIO.ASM ;**************************************** ;* TIPC Scheme Runtime Support * ;* File IO - MS-DOS Version 2.1 * ;* * ;* (C) Copyright 1985 by Texas * ;* Instruments Incorporated. * ;* All rights reserved. * ;* * ;* Date Written: 21 January 1985 * ;* Last Modification: 26 September 1986 * ;**************************************** page 60,132 include scheme.equ include pcmake.equ MSDOS equ 021h TI_CRT equ 049h IBM_CRT equ 010h TI_KEYBD equ 04Ah IBM_KEYB equ 016h MAX_COLS equ 80 MAX_ROWS equ 25 CURSMASK equ 10011111b ; The zeros are the bits that disable cursor NOCURSOR equ 00100000b ; byte mask to disable cursor DGROUP group data data segment word public 'DATA' assume DS:DGROUP public zapcurs,curs_sav, ega_col, ega_row zapcurs dw 0 ; for disabling cursor altogether curs_sav dw 400Ch ; For saving the cursor size when it's ; disabled. Default value just in case... ega_col db ? ega_row db ? c_row dw ? c_col dw ? c_len dw ? banka dw 0a000h sav_di dw ? extrn vid_mode:word extrn cur_off:byte extrn char_hgt:word data ends XGROUP group progx progx segment word public 'progx' assume CS:XGROUP extrn z%border:far ; border drawer extrn crt_dsr:far ; use machine appropriate VIDEO interrupt extrn save%scr:far ; save screen extrn rest%scr:far ; restore screen extrn ega_curs:far ; display an ega cursor extrn enable:far ; part of the ega cursor routine ;************************************************************************ ;* Generate a Bell Character * ;* * ;* Purpose: To generate a "bell character" (i.e., make a noise) to * ;* simulate the effect of outputting a bell character * ;* (control-G) in the output stream. * ;* * ;* Calling Sequence: zbell(); * ;* * ;* Input Parameters: None. * ;* * ;* Output Parameters: None. * ;* * ;************************************************************************ public zbell zbell proc far cmp DGROUP:PC_MAKE,TIPC jne zbmbell zbwait: mov AH,1 ; Get speaker status int 48h jnz zbwait ; wait for bell to turn off mov AH,2 ; Set speaker frequency mov CX,1563 ; Value for 1.25MHz/800Hz (system beep) int 48h mov AX,000Ah ; Turn speaker on for AL*25-ms. 0Ah = .25-sec int 48h ret ; return to caller ; zbmbell: mov BX,080h ; ****Copied from IBM-PC/XT BIOS listing**** in AL,61h push AX ; Save beep_cycle: and AL,0FCh ; Turn off timer gate and speaker data out 61h,AL ; output to control mov CX,48h ; Half cycle time for TONE here: loop here ; speaker off or AL,2 ; Turn speaker on out 61h,AL mov CX,48h here2: loop here2 dec BX ; Decrease cycle count jnz beep_cycle pop AX out 61h,AL ret zbell endp public zch_rdy zch_rdy proc far ; IFDEF extmem ; Kludge to fix hanging keyboard ; mov AL,0AEh ; Ensure keyboard enabled ; out 64h,AL ; Output to 8042 controller ; ENDIF mov AH,01h ; load "check keyboard status" function code cmp pc_make,TIPC ; TI or IBM flavored PC? jne zch_IBM int TI_KEYBD ; issue TI keyboard DSR service call jz zch_no ; is character buffered? if not, jump zch_yes: xor AH,AH ; clear high order byte of AX cmp AL,0 ; test next character to be read jne zch_ret ; binary zero? if not, jump mov AX,256 ; if character is 0, make it non-zero zch_ret: ret ; return (true) zch_IBM: int IBM_KEYB ; issue IBM keyboard DSR service call jnz zch_yes ; is character buffered? if so, jump zch_no: xor AX,AX ; set result = false ret ; return (false) zch_rdy endp zop_args struc dd ? ; far CS and IP dw ? ; caller's BP dw ? ; return address zhandle dw ? ; address of handle zpathnam dw ? ; address of string containing file pathname zmode dw ? ; mode: 0=read, 1=write, 2=read/write zhigh dw ? ; address of high word of file size zlow dw ? ; address of low word of file size zop_args ends public z%open z%open proc far push BP ; save caller's BP mov BP,SP mov AH,03Dh ; load function request id mov AL,byte ptr [BP].zmode ; load access code (mode) mov DX,[BP].zpathnam ; load pointer to pathname int MSDOS ; issue open request jc zop_ret ; if error, jump mov BX,[BP].zhandle ; load address of handle mov [BX],AX ; and store returned handle value ; push AX ; save file handle mov BX,AX ; set bx to file handle xor CX,CX xor DX,DX mov AX,4202h ; poisition file pointer at eof int MSDOS ; mov BX,[BP].zhigh ; load address of hsize mov [BX],DX ; and store returned hsize value mov BX,[BP].zlow ; load address of lsize mov [BX],AX ; and store returned lsize value ; pop BX ; retrieve file handle xor CX,CX xor DX,DX mov AX,4200h ; reset file pointer to begining of file int MSDOS ; xor AX,AX ; set return code for normal return zop_ret: pop BP ; restore caller's BP ret ; return z%open endp public z%create z%create proc far push BP ; save caller's BP mov BP,SP mov AH,03Ch ; load function request id mov DX,[BP].zpathnam ; load pointer to pathname mov CX,020h ; create with "archive" attribute int MSDOS ; issue create request jc zcr_ret ; if error, jump mov BX,[BP].zhandle ; load address of handle mov [BX],AX ; and store returned handle value xor AX,AX ; set return code for normal return zcr_ret: pop BP ; restore caller's BP ret ; return z%create endp public z%close z%close proc far push BP ; save caller's BP mov BP,SP mov AH,03Eh ; load function request id mov BX,[BP].zhandle ; load handle of file to close int MSDOS ; issue close request jc zcl_ret ; if error, jump xor AX,AX ; set return code for normal return zcl_ret: pop BP ; restore caller's BP ret ; return z%close endp zrw_args struc dd ? ; far cs and ip dw ? ; caller's BP dw ? ; return address dw ? ; zhandle (use previous equate) zbuffer dw ? ; input/output buffer zlength dw ? ; address of length value zrw_args ends public z%read z%read proc far push BP ; save caller's BP mov BP,SP mov AH,03Fh ; load function request id mov DX,[BP].zbuffer ; load address of input buffer mov BX,[BP].zlength ; load address of length value mov CX,[BX] ; then load length for read mov BX,[BP].zhandle ; load file's handle int MSDOS ; issue create request jc zrd_ret ; if error, jump mov BX,[BP].zlength ; load address of length parameter mov [BX],AX ; and store number of characters read xor AX,AX ; set return code for normal return zrd_ret: pop BP ; restore caller's BP ret ; return z%read endp public z%write z%write proc far push BP ; save caller's BP mov BP,SP mov AH,040h ; load function request id mov DX,[BP].zbuffer ; load address of input buffer mov BX,[BP].zlength ; load address of length value mov CX,[BX] ; then load length for write mov BX,[BP].zhandle ; load file's handle int MSDOS ; issue write request jc zwr_ret ; if error, jump mov BX,[BP].zlength ; load address of length parameter mov [BX],AX ; and store number of characters written xor AX,AX ; set return code for normal return zwr_ret: pop BP ; restore caller's BP ret ; return z%write endp strd struc dd ? ; far cs and ip dw ?,? ;Caller's BP, Return address strdpg dw ? ;Page, displacement of port strdds dw ? strdbuf dw ? ;Buffer address strdlen dw ? ;Length address strd ends public string%rd string%rd proc far push BP mov BP,SP push DS ;Save caller's DS, ES mov AX,ES ; (and make AX nonzero as well) mov BX,[BP].strdlen ;Load CX with number of chars to transfer mov CX,[BX] mov DI,[BP].strdpg ;Get port page mov DX,DI ; and save for later %LoadPage DS,DI ;Get para address mov DI,[BP].strdds ;DS:DI point to port mov SI,word ptr[DI+car].pt_ptr ;Point DS:SI to string mov BL,[DI+car_page].pt_ptr xor BH,BH %LoadPage DS,BX ;;; mov DS,ES:pagetabl+[BX] cmp byte ptr[SI],STRTYPE ;Is this a string? jne nostr ;Jump if not (error) mov BX,[SI].str_len ;Else fetch string length cmp BX,0 ;;; check for small string jge strn_01 add BX,BLK_OVHD+PTRSIZE strn_01: %LoadPage ES,DX ;Restore ptr to port mov DX,ES:[DI].pt_ullin ;Fetch position within string sub BX,DX ;Set BX to # of chars left jns notpast ;If not negative, skip xor BX,BX ;Set # of chars left to 0 notpast: cmp BX,CX ;Set CX to # of chars left or maximum jae max ; called for, whichever is smaller mov CX,BX max: add SI,DX ;Adjust SI into string add DX,CX ;Reset pointer into string mov ES:[DI].pt_ullin,DX mov ES,AX ;Restore C's ES mov DI,[BP].strdbuf ;Point DI to buffer xor AX,AX ;Prepare to return 0 (all's well) jmp short storlen ;Store # of chars nostr: xor CX,CX ;When not a string, move no chars storlen: mov BX,[BP].strdlen ;Set LENGTH to # of chars read mov ES:[BX],CX rep movsb ;Transfer bytes pop DS ;Restore caller's DS pop BP ret string%rd endp ;************************************************************************ ;* Buffered Keyboard Input * ;* * ;* Calling Sequence: ch = getch(); * ;* where ch - the character read from the keyboard * ;************************************************************************ public get%ch get%ch proc far ; IFDEF extmem ; Kludge to fix hanging keyboard ; mov AL,0AEh ; Ensure keyboard enabled ; out 64h,AL ; Output to 8042 controller ; ENDIF mov AH,07h ; function code = Direct Console Input int MSDOS ; do it xor AH,AH ; clear the high order byte ret ; return to caller get%ch endp z%ega proc far mov AX,banka mov ES,AX ; set ES to the video plane mov AX,c_row ; set AX to the row mul char_hgt ; multiply by the character height mov BX,80 ; multiply by 80 bytes per line mul BX add AX,c_col ; add in the starting column mov sav_di,AX ; save the starting value xor BX,BX ; use BX as a counter mov DX,c_len ; number of columns to blank zc_03: mov CX,DX ; restore counter mov DI,sav_di ; restore index mov AH,0fh call enable ; enable all banks xor AX,AX ; clear AX cld rep stosb add sav_di,80 ; next line inc BX ; increment counter cmp BX,char_hgt ; done with this row? jne zc_03 xor BX,BX ; clear counter dec [BP].zc_nrows ; decrement row count jg zc_03 ; if more rows, loop (jump) ret z%ega endp progx ends PGROUP group prog prog segment byte public 'PROG' assume CS:PGROUP ;************************************************************************ ;* Create a File * ;* * ;* Calling sequence: stat = zcreate(handle, pathname) * ;* where: int *handle - location to store handle * ;* returned by open request* ;* char *pathname - zero terminated string * ;* containing the file's * ;* pathname * ;* int stat - the completion code * ;* 0=no errors * ;* 3=path not found * ;* 4=too many open files * ;* 5=access denied * ;************************************************************************ public zcreate zcreate proc near call z%create ret ; return zcreate endp ;************************************************************************ ;* Open a File * ;* * ;* Calling sequence: stat = zopen(handle, pathname, access_code) * ;* where: int *handle - location to store handle * ;* returned by open request* ;* char *pathname - zero terminated string * ;* containing the file's * ;* pathname * ;* int access_code - 0=read, 1=write, * ;* 2=read and write * ;* int stat - the completion code * ;* 0=no errors * ;* 2=file not found * ;* 4=too many open files * ;* 5=access denied * ;* 12=invalid access * ;************************************************************************ public zopen zopen proc near call z%open ret ; return zopen endp ;************************************************************************ ;* Close a File * ;* * ;* Calling sequence: stat = zclose(handle) * ;* where: int handle - handle returned by open * ;* request * ;* int stat - the completion code * ;* 0=no errors * ;* 6=invalid handle * ;************************************************************************ public zclose zclose proc near call z%close ret ; return zclose endp ;************************************************************************ ;* Read From a File * ;* * ;* Calling sequence: stat = zread(handle, buffer, length) * ;* where: int handle - handle returned by open * ;* request * ;* char *buffer - address of character * ;* buffer into which data * ;* is to be read * ;* int *length - on input, the maximum * ;* number of characters * ;* which the buffer will * ;* hold. On output, the * ;* number of characters * ;* actually read. Note: * ;* a return value of zero * ;* characters read * ;* indicates end of file. * ;* int stat - the completion code * ;* 0=no errors * ;* 5=access denied * ;* 6=invalid handle * ;************************************************************************ public zread zread proc near call z%read ret ; return zread endp ;************************************************************************ ;* Write to a File * ;* * ;* Calling sequence: stat = zwrite(handle, buffer, length) * ;* where: int handle - handle returned by open * ;* char *buffer - address of character * ;* buffer from which data * ;* is to be written * ;* int *length - on input, the number of * ;* characters to write. * ;* The actual number of * ;* characters which were * ;* written is returned in * ;* "length" * ;* int stat - the completion code * ;* 0=no errors * ;* 5=access denied * ;* 6=invalid handle * ;************************************************************************ public zwrite zwrite proc near call z%write ret ; return zwrite endp ;************************************************************************ ;* Clear a Window * ;************************************************************************ zc_args struc dw ? ; caller's BP dw ? ; return address zc_row dw ? ; upper left hand corner row number zc_col dw ? ; upper left hand corner column number zc_nrows dw ? ; number of rows zc_len dw ? ; line length (number of characters) zc_attrib dw ? ; character attributes zc_args ends public zclear zclear proc near push BP ; save caller's BP mov BP,SP push ES push DI push AX push BX push CX push DX ; Put cursor at beginning of next row zc_loop: mov DL,byte ptr [BP].zc_row ; load current row number mov DH,byte ptr [BP].zc_col ; load starting column number xor BH,BH ; page number (0 if in graphics mode) mov AH,02H ; load "put cursor" code call crt_dsr ; position the cursor ; Write line of blanks at current cursor position mov AX,0920h ; load write char/attr code + blank (= 20h) xor BH,BH ; (for IBM-PC BH=display page #) mov BL,byte ptr [BP].zc_attrib ; load attribute flag cmp vid_mode,14 ; IBM EGA modes? jl zc_01 cmp BL,87h ; attribute is rv white? jne zc_22 mov AX,09dbh ; use the block character not the blank and BL,7fh ; strip off the xor bit zc_01: mov CX,[BP].zc_len ; load number of times to write the blank call crt_dsr ; perform the write ; Increment row number, decrement row count, test, loop inc [BP].zc_row ; increment row number dec [BP].zc_nrows ; decrement row count jg zc_loop ; if more rows, loop (jump) ; Return to caller zc_end: pop DX pop CX pop BX pop AX pop DI pop ES pop BP ; restore caller's BP ret ; return ; clear out the line by writing directly to the graphics planes zc_22: mov AX,[BP].zc_row ; set AX to the row mov c_row,AX mov AX,[BP].zc_col ; add in the starting column mov c_col,AX mov AX,[BP].zc_len ; number of columns to blank mov c_len,AX call z%ega ; restore counter jmp zc_end ; return zclear endp ;************************************************************************ ;* Draw Border * ;************************************************************************ zb_args struc dw ? ; caller's BP dw ? ; return address zb_line dw ? ; upper left corner line number zb_col dw ? ; upper left corner column number zb_nlines dw ? ; number of lines zb_ncols dw ? ; number of columns zb_battr dw ? ; border attributes zb_label dw ? ; pointer to label text zb_args ends public zborder zborder proc near call z%border ret zborder endp ;************************************************************************ ;* Link to Save Screen Support * ;************************************************************************ public save_scr save_scr proc near call save%scr ret save_scr endp ;************************************************************************ ;* Link to Restore Screen Support * ;************************************************************************ public rest_scr rest_scr proc near call rest%scr ret rest_scr endp ;************************************************************************ ;* Cursor Off * ;************************************************************************ public zcuroff zcuroff proc near call ega_curs mov AH,03 xor BH,BH ; IBM page number/must be 0 for graphics mode call crt_dsr ; get the cursor position/mode cmp zapcurs,0 jne zcoff_01 mov curs_sav,CX ; save it for restoration zcoff_01: and CH,CURSMASK ; mask off bits to select cursor type or CH,NOCURSOR ; disables cursor (turns it off) mov AH,01h ; load "set cursor type" code call crt_dsr ; turn the cursor off ret ; return to caller zcuroff endp ;************************************************************************ ;* Cursor On * ;************************************************************************ public zcuron zcuron proc near cmp zapcurs,0 ; if cursor disabled jne zcon_ret ; then return mov CX,curs_sav ; attributes for cursor on mov AH,01h ; load "set cursor type" code call crt_dsr ; turn the cursor on zcon_ret: ret ; return to caller zcuron endp ;************************************************************************ ;* Put Cursor * ;************************************************************************ public zputcur zputcur proc near push BP ; save caller's BP mov BP,SP ; put cursor in desired location mov DH,byte ptr [BP].zc_col ; load column number mov ega_col,DH mov DL,byte ptr [BP].zc_row ; load row number mov ega_row,DL xor BH,BH ; IBMism: page number (0 if in graphics mode) mov AH,02H ; load "put cursor" code call crt_dsr ; position the cursor (DSR swaps DH/DL) call ega_curs ; display cursor for ega mode ; Return to caller pop BP ; restore caller's BP ret ; return zputcur endp ;************************************************************************ ;* Scroll a Window * ;************************************************************************ zs_args struc dw ? ; caller's BP dw ? ; return address zs_line dw ? ; upper left hand corner line number zs_col dw ? ; upper left hand corner column number zs_nline dw ? ; number of lines zs_ncols dw ? ; number of columns zs_attr dw ? ; text attributes (used for blanking) zs_args ends public zscroll zscroll proc near push BP ; save caller's BP mov BP,SP push AX push BX push CX push DX ; scroll window's text up one line mov CL,byte ptr [BP].zs_nline ; load number of lines dec CL ; decrease number of lines by one jz blank1 ; Jump if scrolling 1-line and just blank it mov CH,byte ptr [BP].zs_ncols ; load number of columns mov DL,byte ptr [BP].zs_line ; load upper left line number mov DH,byte ptr [BP].zs_col ; load upper left column number mov AX,0601h ; load "scroll text" code with no blanking cmp DGROUP:PC_MAKE,TIPC je ti_scrl ;;;;;;;;; cmp vid_mode,14 ;;;;;;;;; jge txt_mod ; treat ega modes as text cmp vid_mode,4 ; Are we in graphics mode? jl txt_mod ; If we are then fix blank fill attributes cmp vid_mode,7 ; so that the bar characters don't show up je txt_mod xor BH,BH ; zero attribute for fill blanks jmp short rite_atr txt_mod: mov BH,byte ptr [BP].zs_attr ; Blanked lines' attribute txt mode rite_atr: xchg CX,DX ; CX=Upper left corner xchg CH,CL ; Row,column instead of TI's column,row xchg DH,DL ; ditto add DX,CX ; DX=Lower right corner dec DL ; adjust column count (0 is first column) int IBM_CRT jmp short z_quit ; IFF IBM is in graphics mode weird char's ; are used for blanks when scrolling. Do ; as TIPC does and "manual" blank 'em. ; ti_scrl: mov BX,DX ; copy destination coordinates inc DL ; compute source by incrementing line number int TI_CRT ; perform block move ; paint the last line of the window with blank of proper attributes blank1: mov DH,byte ptr [BP].zs_col ; load starting column number mov DL,byte ptr [BP].zs_line ; load upper line number add DL,byte ptr [BP].zs_nline ; add the number of lines and dec DL ; subtract offf one mov AH,02h ; load "put cursor" code xor BH,BH ; IBMism call crt_dsr ; position cursor for write mov AX,0920h ; load "write char/attr" code, write a blank mov BL,byte ptr [BP].zs_attr ; load attribute bit setting cmp vid_mode,14 ; ega mode? jl z_scr01 mov BH,BL and BH,80h cmp BH,80h ; reverse video? jne z_scr01 mov AX,09dbh ; change for block character and BL,7fh ; strip off xor bit z_scr01: xor BH,BH ; IBMism mov CX,[BP].zs_ncols ; load line length call crt_dsr ; write a line of blanks ; return to caller z_quit: pop DX ; restore caller's BP pop CX pop BX pop AX pop BP ret zscroll endp ;************************************************************************ ;* Output Character To Window * ;************************************************************************ zp_args struc dw ? ; caller's BP dw ? ; return address zp_line dw ? ; cursor position - line number zp_col dw ? ; cursor position - column number zp_char dw ? ; character to write zp_attr dw ? ; character's attributes zp_args ends public zputc zputc proc near push BP ; save caller's BP mov BP,SP push DX push CX push BX push AX ; position cursor for write mov DL,byte ptr [BP].zp_line ; load line number mov DH,byte ptr [BP].zp_col ; load column number xor BH,BH ; IBMism mov AH,02h ; load "put cursor" code call crt_dsr ; positio the cursor mov BL,byte ptr [BP].zp_attr ; load its attributes cmp vid_mode,14 ; only attribute for EGA modes is a jl zchar_1 ; simulated reverse video mov BH,BL ; save the attribute and BH,80h ; reverse video? jz zchar_1 ; zero indicates bit 8 not set zchar_2: and BL,7fh ; strip off high bit mov CX,1 ; character count xor BH,BH ; video page number mov AL,0dbh ; block character mov AH,09h call crt_dsr or BL,80h ; set xor bit ; write the characters with attributes zchar_1: mov AL,byte ptr [BP].zp_char ; load the character xor BH,BH ; IBMism mov CX,1 ; repeat count = 1 mov AH,09h ; load write char/attribute code call crt_dsr ; return to caller pop AX pop BX pop CX pop DX pop BP ret zputc endp ;************************************************************************ ;* Buffered Keyboard Input * ;* * ;* Calling Sequence: ch = getch(); * ;* where ch - the character read from the keyboard * ;************************************************************************ public getch getch proc near call get%ch ret ; return to caller getch endp ;************************************************************************ ;* Read characters from a string * ;* * ;* Calling Sequence: stringrd(page, disp, buffer, &length) * ;* where page,disp: location of string-fed port * ;* buffer and length are as in ZREAD (see above) * ;* * ;* Note: The passing parameter `page' is page # * ;************************************************************************ public stringrd stringrd proc near call string%rd ret stringrd endp ;*************************************************************************** ;* Link for routines in PROGX * ;*************************************************************************** extrn shft_brk:near extrn dos_err:near public shft%brk public dos%err shft%brk proc far call shft_brk ;link to SHF BREAK process ret shft%brk endp dos%err proc far call dos_err ;link to DOS fatal error process ret dos%err endp ; public char_rdy char_rdy proc near ;our equivalent of Lattice C's kbhit fn call zch_rdy ret char_rdy endp prog ends end