title 'BISHOW.ASM' ;A buffered, bidirectional version of SHOW.ASM. ;Ver 1.0, 23 Aug 82 ;Phil Cary, 748 Kenilworth Parkway, Baton Rouge, LA 70808 ;Ver 1.1, 30 Mar 83 added BDOS function 6 W.F.McGee ;Ver 1.2, 22 May 83 added hi-bit mask for WordStar files ; and Wyse-100/200 SCRL keys-changed messages ; also made CP/M-86 ver using XLT86 see A86 file ; H.M. Van Tassell ;BISHOW is a buffered, bidirectional version of SHOW.ASM which first ;appeared in Interface Age, November, 1981. That program could ;only scroll forward in a file, and read sectors from disk one at a ;time as they were sent to the console. I used SHOW frequently to take ;a quick look at a file without loading a big text editor, and to examine ;another file with the RUN command while in Wordstar. TYPE does not work ;since it is not a file that Wordstar can load and run. ; ;It was annoying when I went past the point I was looking for in a file ;with SHOW, and could not go backwards. Thus, this bidirectional version ;which uses random access reads. In addition, buffering was added so that ;the number of disk reads would be reduced, and moving back and forth ;in a moderate sized file would be speeded up. There is a trade off ;between the size of the buffer and the length of time it takes to refill ;the buffer which should be set to the user's preference. ; ;There are three customizing items in this program. One is the equate ;"maxsec" which sets the buffer size. The other is the string in the ;subroutine "clrscr" just after the org statement. This should be changed ;to the erase screen and home cursor sequence for the user's terminal. The ;program is presently set up for a H/Z-19. The program, as written, does ;require a 24 X 80 screen with an erase screen and home cursor function. ;Finally, direct I/O to the console is used to avoid echoing the commands ;to the console as the CP/M write console function does. Three equates ;under "Console equates" must be changed to match the user's system. ; ;Just a small contribution to the public domain software as partial ;payment for the many fine and educational programs the system has ;given me. Phil Cary. ; Begin code false equ 0 true equ not false APPLE EQU false ; BDOS equates boot equ 0 ;warm boot wrcon equ 2 ;console write bdos equ 5 ;bdos entry open equ 15 ;open file readr equ 33 ;read file random access stdma equ 26 ;set dma address ; FCB equates fcb equ 05ch ;default fcb drive number fcbfn equ fcb+1 ;start of filename fcbft equ fcb+9 ;start of filetype fcbex equ fcb+12 ;current extent number fcbcrr equ fcb+33 ;current record number, random access ; ASCII equates cr equ 0dh ;carriage return lf equ 0ah ;line feed eof equ 01ah ;end of file esc equ 01bh ;escape bell equ 07h ;bell ; Operational equates maxsec equ 64 ;number of sectors in buffer org 100h fulbuf: set dskbuf+(maxsec*128) ;need to know end of buffer jmp start ;skip over next subroutine clrscr: call ilprt ;code to erase screen and home cursor IF NOT APPLE db esc,'*',0 ;..Wyse-100/200 terminal. change as required ENDIF IF APPLE db esc,'*',0 ;..for terminal screen function table ENDIF ret start: lxi sp,stack ;set up local stack call clrscr ;clear the screen call opnfil ;open file in default fcb xra a ;get a 0 sta lincnt ;store in line count sta fcbex ;zero current extent sta fcbcrr ;zero current record sta fcbcrr+1 ;..both bytes sta fcbcrr+2 ;..and the overflow call filbuf ;fill the disk buffer wrtfwd: lxi h,dskbuf ;point to beginning of buffer wrtfwd1 mov a,m ;get a character cpi eof ;if it is EOF jz getcmd ;..loop for another command push psw ;save character from BDOS clobber call ctype ;put it on console pop psw ;get character ani 7fh ;strip hi bit cpi cr ;see if end of line jz fwdcnt ;yes, count line wrtfwd2 inx h ;no, bump buffer lxi d,fulbuf ;get end of buffer address mov a,d ;compare high cmp h ;..order bytes jnz wrtfwd1 ;if not equal, continue mov a,e ;else compare low cmp l ;..order bytes cz filbuf ;if end of buffer, go refill jz wrtfwd ;..and start at beginning of buffer jmp wrtfwd1 ;else, continue with next character fwdcnt: lda lincnt ;get number of lines displayed inr a ;bump it sta lincnt ;..and store it xchg ;save the buffer pointer lxi h,linmax ;point to max number of line for this pass cmp m ;compare with line count xchg ;restore pointer jnz wrtfwd2 ;if not there, continue, else get command xra a ;zero the sta lincnt ;..line count getcmd: push h push d push b getcmd1: mvi c,06 mvi e,0FFH call bdos cmp 00h jz getcmd1 cpi esc ;skip if esc jz getcmd1 ani 5fH ;make it upper case push psw ;save chars mvi a,22 ;set up for only 22 lines on forward sta linmax ;..scrolls pop psw ;get flags pop b pop d pop h cpi 'W' ;scroll forward?-WYSE-100 SCRL DOWN jz wrtfwd1 ;scroll forward cpi 'C'-40h ;CTRL C jz wrtfwd1 cpi 'Z'-40h ;CTRL Z jz wrtfwd1 push psw ;else save character and flags again mvi a,24 ;set up for full screen on scroll sta linmax ;..backward pop psw ;get character cpi 'V' ;scroll backward?-WYSE-100 SCRL UP jz wrtbak ;yes cpi 'R'-40h ;CTRL R? jz wrtbak ;yes cpi 'W'-40h ;CTRL W? jz wrtbak ;yes cpi 'X' ;must be exit jz exit ;yes, or call ilprt ;..a wrong choice so give message db cr,lf,lf,'Use the SCRL keys (or ^C,^R) to go forward and backward, ' db 'or X to exit.',cr,bell,0 jmp getcmd ;try again for command wrtbak mvi a,44 sta lincnt call clrscr ;clear the screen wrtbak1 lxi d,dskbuf ;get address of buffer start mov a,d ;compare high cmp h ;..order bytes jnz wrtbak2 ;continue if not equal mov a,e ;else, compare low cmp l ;..order bytes jnz wrtbak2 ;continue if not equal jmp filbak ;..and go write it wrtbak2 mov a,m ;get a character ani 7fh ;strip hi bit cpi cr ;see if end of line dcx h ;decrement buffer jnz wrtbak1 ;..and loop if not bakcnt: lda lincnt ;else, get number of lines to move back dcr a ;..and decrement it sta lincnt ;..store it jnz wrtbak1 ;..and loop if not there inx h ;else bump pointer to account for lf with cr jmp wrtfwd1 ;..and go write a screen filbak: lxi d,maxsec ;get the buffer size lhld seccnt ;..and number of sectors last read dad d ;add them xchg ;..and put them in DE lda fcbcrr ;subtract low order byte sub e ;..from current record count sta fcbcrr ;..and store in current record count lda fcbcrr+1 ;same with high order byte sbb d ;..but with borrow jm filbeg ;if beyond beginning of file, go zero count sta fcbcrr+1 ;else, store high order byte call filbuf ;fill the buffer lxi h,fulbuf ;..and point to end of buffer call clrscr ;clear the screen jmp wrtbak2 ;continue moving back in file filbeg: xra a ;if beyond beginning of file sta fcbcrr ;..zero the current record field sta fcbcrr+1 sta lincnt ;..and the line count call filbuf ;fill the buffer again jmp wrtfwd ;..and go write it filbuf: lxi d,dskbuf ;load start of disk buffer mvi b,maxsec ;number of sectors to resd lxi h,0 ;zero out the shld seccnt ;..number of sectors in buffer filbuf1 push h ;save all push d ;..registers from push b ;..BDOS clobber mvi c,stdma ;set dma to call bdos ;..disk buffer lxi d,fcb ;set up to read mvi c,readr ;..a record call bdos ;do it cpi 0 ;read OK? lhld fcbcrr ;get current record number inx h ;..bump it shld fcbcrr ;..and save it lhld seccnt ;get sectors in buffer inx h ;bump it shld seccnt ;store it jnz rderr ;no, last sector read pop b ;yes, get sector count dcr b ;decrement it pop d ;get de off stack to expose return address pop h ; rz ;if done return lxi h,128 ;else, add 128 to dad d ;..dma address xchg ;put it in de jmp filbuf1 ;read another sector rderr: pop b ;restore pop d ;..registers pop h ;..and xra a ;..get a zero to direct to start of buffer ret ;..on ret opnfil: lda fcbfn ;point to first letter of filename cpi ' ' ;anything there? jz help ;no, give help message lxi d,fcb ;file name in default fcb mvi c,open ;set up to open call bdos ;do it cpi 0ffh ;open OK? rnz ;yes call ilprt ;else, give error msg and quit db cr,lf,lf,'Requested file is not on this disk.',cr,lf,bell db 'Please check your spelling or use DIR.',cr,lf,lf,bell,0 jmp exit1 ;leave msg on screen on exit help: call ilprt db 'Correct usage of SHOW is --',cr,lf,lf db ' A>SHOW filename ',cr,lf,lf db 'After first page is displayed, ' db 'press SCRL down (^C) for forward,' db cr,lf db 'and SCRL up (^R) for backward, or X to exit.',bell,cr,lf,lf,0 jmp exit1 ilprt: xthl ;exchange top of stack and HL ilprt1 mov a,m ;HL now pointing to db message ora a ;see if 0 at end of message jz ilprt2 ;yes, restore stack and return call ctype ;no, print the character inx h ;bump the pointer jmp ilprt1 ;..and loop ilprt2 xthl ;get return address on top of stack ret ;..and return ctype: push b ;Save the registers push d ;..from bdos push h ;..clobber cpi 'O'-40h ;wordstar uses ^O for jnz notco ;non-break space mvi a,' ' ;so substitute a space notco: ani 7fh ;strip hi bit mov e,a ;set up character mvi c,wrcon ;..to send to console call bdos ;do it pop h ;restore pop d ;..the registers pop b ret exit: call clrscr ;clear the screen exit1 jmp 0 ;warm boot ; Memory allocation seccnt: dw 0 ;number of sectors read into buffer linmax: db 24 ;number of to write lines on console lincnt: db 0 ;line number on write or move back in buffer ds 60 ;stack area stack: ds 2 dskbuf: equ $ ;disk buffer area above the program end 100h