NAME LD40 VERS EQU 400 ; = version 40.0 as of 7-19-86. ; previous version 2.26. ; Assembled with SLR Systems Assembler. ; If using MACRO-80 , delete the semicolons in the next 2 lines. ; .Z80 ; use with M80 ; ASEG ; ditto ; ********* N O T I C E S ********* ; ; This program was originated by: ; Jon Lindsay ; 150 N. Jackson Ave., Suite 108 ; San Jose, CA 95116 ; Tel. (408) 272-4800 weekdays ; My thanks go out to Jon for providing a good base to work ; from in his original creation of LD. Many of the features ; however were specific to the Kaypro screen presentation. ; There were other things not present that I had often wished ; for. With much of the base done, it gave me the impetus to ; add to and modify the original. ; Joe Field ; 22 Speare Road ; Hudson, N.H., 03051 ; Tel. 603-893-1983 (days), 603-883-2823 (evenings) ; Revisers releasing new versions are asked to only ; change the version number by 1 digit in the ; last two places unless it is a major revision (such as to ; a very specific machine. ; ; ; ********ª R E V I S I O N S ********* ; Joe Field ; 3-86 to 7-19-86: ; ; Removed: Kaypro specific cmds including WS specific. ; Autojump to directory. ; Direct bios calls (didn't speed up my system). ; ; Changed: Changed (L) cmd to start lines at top of crt, not middle. ; Set number of lines displayed to 23. ; (+) provides same function as cr (forward page). ; Fixed extraneous character on return to CPM by using ; call 1 instead of 6 and then blanking out extra character. ; Moved most of the variables to the end of the program. ; ; Added: Printing of current page (P) or range of lines, n to m. ; Turn off/on line numbers (O), while retaining reference. ; Auto scroll (S) (continuous until char other than digit), ; value sets speed of scroll. 0 = slowest, 9 = fastest. ; Ability to get another file while in LD. ; Check file sizes, allow to overwrite ccp, but not bdos. ; Now failsafe. Announce shortened file when needed. ; If short file, exit without warm boot for speed of exit. ; Announce end of text area, disallow paging past end. ; Filter out control characters (Wordstar) so that screen ; and printer don't get confused. ; Jon Lindsay ; ;01-23-86: turn off keyclick automatically ;01-16-86: make CCP base calculation universal ;01-11-86: add auto COM file loader routine ;12-12-85: add version # routine ;11-29-85: reverse video to QUIT msg. ;11-24-85: speed up PRTLN routine. ; modify tab expansion for 'F' and 'L' ;11-14-85: duplicate f.# 10 (as DINP10) because ; of apparent bug in f.# 10 operation. ; A char. entered (INP6) turned up as ; the first char. of edited input (INP10) ;11-13-85: run output thru BIOS (for speed) ;11-11-85: char. output thru BIOS ( VCHR ) ;11-10-85: speed up single line display ;10-17-85: add ^L to continue search ; ;->equates LF EQU 0AH ;linefeed CR EQU 0DH ;carriage return BELL EQU 07 ; bell BS EQU 08 ;standard backspace ESC EQU 1BH ;escape key DOL EQU '$' ;terminator SPC EQU ' ' ;space TAB EQU 09H ;tab BDOS EQU 5 ;CP/M entry FCB EQU 5CH ;File Control Block loc. TIME EQU 0FFH ;timer value TABSIZ EQU 8 ;makes tabs = 8 spaces BASE EQU 0 LNPPG EQU 17 ;lines per page less an offset. LNCNR EQU 0023 ; ; ; ORG 100H JP LAB0 ;bypass stack ; DEFS 20H ;stack size STACK:: DEFB 0 ;top of stack OLDSP:: DEFW 0 ;old stack ptr ; LAB0:: LD HL,0 ADD HL,SP LD (OLDSP),HL LAB1:: LD SP,STACK ;%% identify stack, jmp here from N. LD B,BUFF-TDMA ;%% fill this area with 00 to LD A,00 ;%% insure proper restart. LD HL,TDMA LAB2:: LD (HL),A INC HL DEC B JP NZ,LAB2 ;%% ; LD HL,(BASE+6) ; calc top of memory. DEC H ; leave 80h space. LD L,80h ; LD (TOPMEM),HL ; save for later. LD DE,800H ; length of ccp. SBC HL,DE ; calc free area before LD (PRECCP),HL ; warm boot required on exit. ; ;------------------------------ ZZZ:: NXLAB:: CALL CLS ;clear screen LD DE,SIGNON ;<- new CALL PRSTR ;<- new CALL FILINT ;file initial. ; ;-> find end of text (eot) LD HL,BUFF FEOT:: LD A,(HL) AND 7FH ;strip bit-7 CP CR ;end of line? CALL Z,ADDLIN ;tally lines CP 0 JP Z,FEOT1 CP 1AH ;cp/m eot? JP Z,FEOT1 INC HL JP FEOT FEOT1:: ;-> if here, mem. pointing to eot LD (EOT),HL JP ED ; ADDLIN:: ;-> find last line of text PUSH HL LD HL,(LASTLIN) INC HL LD (LASTLIN),HL POP HL RET ; ;------------------------------ FILINT:: ;file initial. XOR A LD (FCB+12),A LD (FCB+32),A ;create write fcb LD HL,FCB LD DE,WFCB LD C,33 CALL MOVE ; ;look for valid file LD A,(FCB+1) LD DE,NOFIL CP 20H JP NZ,OPEN CALL PRSTR LD DE,REFIL CALL PRSTR JP NEWFL ; ;open file OPEN:: LD C,15 LD DE,FCB CALL BDOS INC A JP NZ,LOAD ;file present, read it in LD DE,NOFN1 ;else print msg CALL PRSTR CALL HEAD ;with filename LD DE,NOFN2 ; else ask for another. CALL PRSTR LD DE,REFIL CALL PRSTR JP NEWFL ; look for another entry. ; ;'file [ ] now loading' LOAD:: LD DE,WAITA CALL PRSTR CALL HEAD LD DE,WAITB CALL PRSTR ; CALL SETDMA READ:: LD DE,FCB LD C,20 CALL BDOS OR A JP NZ,READ1 ;end of file read LD A,'.' ;display dots with each CALL VCHR ; sector read CALL XBUF ; set up fcb for next dma. ; LD HL,(TOPMEM) ;%% check to make sure there LD DE,(TDMA) ;%% is room for another sector. SBC HL,DE JP C,READN ;%% no room. ; LD HL,(PRECCP) ; see if file overwrites ccp. LD DE,(TDMA) SBC HL,DE JR NC,READ4 ; no. LD A,0FFH ; set flag to show overwrite. LD (TMFLG),A ; READ4:: JP READ ; get next sector. READN:: CALL CLS LD DE,MEMFUL CALL PRSTR RET ; READ1:: CALL CRLF ; done with file, so do CRLF CALL CLS RET ;and return to caller ; HEAD:: ;display fcb filename/filetype PUSH HL LD HL,FCB LD C,8 TITA:: INC HL ;print out filename LD A,(HL) CP SPC JP Z,TITB CALL VCHR DEC C JP Z,TITB JP TITA TITB:: LD HL,FCB+9 LD A,(HL) CP SPC JP Z,TITD LD A,'.' ;print dot CALL VCHR LD C,3 DEC HL TITC:: INC HL ;print out filetype LD A,(HL) CP SPC JP Z,TITD CALL VCHR DEC C JP Z,TITD JP TITC TITD:: POP HL RET ; SETDMA:: ;set up dma for read/write LD HL,BUFF SET1:: LD (TDMA),HL EX DE,HL LD C,26 CALL BDOS RET ; XBUF:: ;advance dma by 128 bytes LD HL,(TDMA) LD DE,80H ADD HL,DE JP SET1 ; ;------------------------------ ; ED:: CALL VALGOR JP VIEW ; ; VALGOR:: ;-> view algorithm LD HL,(LNREQ) CALL PAGELN CALL LOCLINE VALGLN::LD BC,LNCNR ;set line counter LD (PGCNT),BC VAL1:: LD A,0 ; clear page not flag. LD (PGFLG),A ; LD A,(LINFLG) ;%% see if line no. CP 0FFH ;%% is requested. JP Z,VAL3B2 ;%% no. ; PUSH HL LD HL,(VLIN) CALL BINDEC EX DE,HL LD HL,(LNREQ) CALL COMP16 POP HL JP Z,VAL2 LD DE,COLON ;': ' JP VAL3 VAL2:: LD DE,COLON ;colast ;':* ' WHAT WAS THIS TO BE? VAL3:: PUSH HL ;save HL EX DE,HL ;colon pointer to reg. HL VAL3A:: LD A,(HL) ;print out colon message CP '$' JP Z,VAL3B CALL VCHR INC HL JP VAL3A VAL3B:: POP HL ;restore HL pointer VAL3B2:: CALL PRTLN CP 0 ;programmer induced EOF JP Z,VAL4 CP 1AH ;actual end of file for CP/M JP Z,VAL4 INC HL INC HL PUSH HL VAL3C:: LD HL,(VLIN) ;page number INC HL LD (VLIN),HL POP HL LD BC,(PGCNT) DEC BC LD (PGCNT),BC LD A,C OR B JP Z,VAL5 JP VAL1 VAL4:: LD (SOL),HL LD HL,(VLIN) LD DE,-1 ;& ADD HL,DE LD (LNREQ),HL LD DE,PASTLN ; announce end of text area. CALL PRSTR RET ; VAL5:: LD (SOL),HL LD HL,(VLIN) LD DE,-1 ADD HL,DE LD (LNREQ),HL RET ; COLON:: DEFB ': $' COLAST::DEFB ':->$' ;-> Moved storage to end of program so it can all ; be reinitialized when getting a new file. ; PRTLN:: ;-> identify & display next line ; assume SOL (HL) LD A,TABSIZ LD (TABVAL),A ; PRTLN1:: PUSH HL ;%% LD DE,(TOPMEM) ;%% see if at end of file SBC HL,DE ;%% in memory (partial file). POP HL ;%% LD A,1AH ;%% fake an eof. JP NC,PRTLN2 ;%% at end. ; LD A,(HL) AND 7FH ;mask bit 7 so can read WS files CP CR ;check for EOL JP Z,PRTLN2 CP 0 ;programmer induce EOF? JP Z,PRTLN2 CP 1AH ;end of file (CP/M)? JP Z,PRTLN2 CP TAB ;tab? CALL Z,TABEXP PUSH HL CALL VCHR ; removed speedup. POP HL CALL TABADJ INC HL JP PRTLN1 PRTLN2:: CALL CRLF RET ; ;------------------------------ ; VINPST::;-> check keyboard entry status, A is zero if no ; char is ready. PUSH BC PUSH DE PUSH HL LD C,11 CALL BDOS OR A ; set zero flag if no char ready. POP HL POP DE POP BC RET ; ;------------------------------ VINP:: ;-> loop until keyboard entry, ; char. returned in reg. A ; PUSH BC PUSH DE PUSH HL VINPA:: LD C,11 ; check status. CALL BDOS OR A ;test for zero JP Z,VINPA ; loop until char is input. ; LD C,1 ; now, get it. CALL BDOS CALL CLEAN ; remove extra char from screen. POP HL POP DE POP BC RET ;------------------------------ VINPY:: ;-> char assumed to be waiting. ; vinpst should have been used prior to this. ; PUSH BC PUSH DE PUSH HL LD C,1 CALL BDOS CALL CLEAN POP HL POP DE POP BC RET ;------------------------------ CLEAN:: ;-> remove the extra char from the screen. extra ; results from bdos console input function. PUSH AF LD DE,CLNMSG LD C,9 CALL BDOS POP AF RET ; CLNMSG::DEFB BS,SPC,BS,'$' ;------------------------------ VCHR:: ;-> reg. A has char. to be displayed ; pflg determines if char is to be printed or sent to crt. ; Do some filtering for wordstar files. ; Remove control chars and ignore. CP 1EH ; soft hyphen, in line. JP Z,VCHEND ; ignore. CP 1FH ; JP NZ,VCH2 ; no. LD A,'-' ; convert to '-'. JP VCH5 ; Get rid of high bits and most control chars. VCH2:: AND 7Fh ; strip bit 7. CP 20H ; space or above ? JP NC,VCH5 ; yes, use it. CP 0EH ; 0Eh to 1Fh. JP NC,VCHEND ; yes, ignore. CP 07H ; 07h to 0Dh ? JP C,VCHEND ; no. ; Done with filter. VCH5:: PUSH AF PUSH BC PUSH DE PUSH HL LD E,A LD A,(PFLG) OR A LD C,2 JP Z,VCHR2 ; to crt. LD C,5 ; to printer. VCHR2:: CALL BDOS POP HL POP DE POP BC POP AF VCHEND::RET ; ;------------------------------ CLS:: ;-> ADM clear screen LD A,26 CALL VCH5 RET ;------------------------------ ; PRCHR:: ;-> send character to list device. PUSH DE PUSH HL LD E,A LD C,5 CALL BDOS POP HL POP DE RET ;------------------------------ LSTR:: ;-> send string to list device until $ is seen. ; de has string location. ; LD A,(DE) CP '$' ; end ? JR Z,LSTEND ; yes. CALL PRCHR INC DE ; next char. JR LSTR LSTEND::RET ; ;------------------------------ ; PRSTR:: ;-> print string to crt ; string message in DE PUSH DE PUSH HL LD C,9 CALL BDOS POP HL POP DE RET ;------------------------------ ; CRLF:: ;-> CR/LF sequence PUSH AF LD A,CR CALL VCHR LD A,LF CALL VCHR POP AF RET ; ;------------------------------ DINP10:: ;-> duplicate f. # INP10 XOR A ;clear reg. A LD (INNC),A ;clear real counter LD A,(INMX) LD C,A LD HL,INCHAR ;point to buffer DINPA:: LD (HL),A ;and clear buffer DEC C JP Z,DINPB ;finished? then continue INC HL JP DINPA ; DINPB:: LD HL,INCHAR ;start of buffer DINPC:: CALL VINP ;get input char. CP CR ;end of input JP Z,DINPE CP TAB ;fix tab CALL Z,TABEXP CP BS ;backspace? JP Z,DINPC1 CP 7FH ;rub? JP Z,DINPC1 ;no, then continue PUSH AF CALL VCHR ;and display it CALL TABADJ ;tab counter LD A,(INNC) INC A ;increment real counter LD (INNC),A POP AF JP DINPD DINPC1:: LD A,(INNC) OR A JP Z,DINPC ;don't BS if no buffer char. LD A,BS CALL VCHR LD A,' ' ;clear previous char. CALL VCHR LD A,BS ;and backup into it CALL VCHR LD A,(INNC) DEC A ;adjust real count LD (INNC),A DEC HL ;adjust mem. pointer JP DINPC DINPD:: ;-> if here, char. good PUSH AF ;save input LD A,(INMX) ;get max. value allowed LD B,A LD A,(INNC) CP B ;at max yet? JP Z,DINPEE ;yes, then quit here POP AF ;restore input LD (HL),A ;load buffer INC HL ;point to next buffer space JP DINPC DINPEE:: POP AF ;adjust stack DINPE:: CALL CRLF RET ; FIXTAB::;-> adjust tab RET ; ;------------------------------ ;%% MOVE:: ;-> move data SPEED UP - USE Z80 ; DE = destination LDIR INSTRUCTION. ; HL = source ; C = counter PUSH BC ; only c should change. LD B,0 LDIR POP BC RET ;return when done ; ;------------------------------ ; DECBIN::;-> decimal to binary ; HL = ASCII value to convert ; C = digit counter ; TOTAL = complete binary number PUSH HL LD HL,0 LD (TOTAL1),HL ;%%% zero out, see if filled later. LD (TOTAL2),HL POP HL DECA:: PUSH HL LD HL,0 LD (TOTAL),HL POP HL DEC1:: LD A,(HL) ;get ASCII digit CP ' ' ; seperator between 2 no's. JP Z,DEC3 ; store 1st result. SUB 30H ;make binary JP C,DEC2 CP 0AH JP NC,DEC2 PUSH HL LD HL,(TOTAL) EX DE,HL LD HL,0 ADD HL,DE ADD HL,HL ADD HL,HL ADD HL,DE ADD HL,HL ; x10 LD E,A LD D,0 ADD HL,DE LD (TOTAL),HL POP HL INC HL DEC C JP NZ,DEC1 LD HL,(TOTAL) RET DEC2:: LD HL,0 LD (TOTAL),HL RET ; DEC3:: DEC C INC HL PUSH HL LD HL,(TOTAL) LD (TOTAL1),HL ; save as first line request. POP HL JP DECA ; ;------------------------------ ; BINDEC:: ;-> binary to decimal ; binary value in HL ; PUSH HL PUSH DE PUSH BC PUSH AF XOR A LD (ZRVAL),A JP BIN1 LD BC,10000 CALL ADJUST BIN1:: LD BC,1000 CALL ADJUST LD BC,100 CALL ADJUST LD BC,10 CALL ADJUST LD A,L ADD A,30H CALL VCHR BIN2:: POP AF POP BC POP DE POP HL RET ADJUST:: LD D,0FFH ADJA:: LD A,L SUB C LD L,A LD A,H SBC A,B LD H,A INC D JP NC,ADJA ADD HL,BC LD A,D OR A JP Z,LEDZR PUSH AF LD A,1 LD (ZRVAL),A POP AF ADJB:: ADD A,30H ADJC:: JP VCHR LEDZR:: ;check leading zero LD A,(ZRVAL) OR A JP NZ,LEDZ1 LD A,SPC JP ADJC LEDZ1:: XOR A JP ADJB ZRVAL:: DEFB 0 ;------------------------------ ; COMP16:: ;-> compare DE to HL ; if match, ZF=1 LD A,L CP E RET NZ LD A,H CP D RET ;------------------------------ ; SUB16:: ;-> HL-DE --> HL (subtract 2 16-bit reg.) ; if DE>HL, CF=1 LD A,L SUB E ;L-E -> A LD L,A ;put in reg. L LD A,H SBC A,D ;H-D -> A LD H,A ;put in reg. H RET ;------------------------------ ; TABEXP:: ;-> expand tab LD A,(TABVAL) ;# of spaces LD C,A TAB1:: OR A JP Z,TAB2 LD A,SPC ;print spaces CALL VCHR DEC C LD A,C JP TAB1 TAB2:: LD A,TABSIZ+1 LD (TABVAL),A LD A,0 ; RETURN A NULL HERE OR RET ; ERRONEOUS TABBING WILL OCCUR ; TABVAL:: DEFB TABSIZ ;%%% MOVE DOWN. ;------------------------------ ; TABADJ:: ;-> do regular tab pos. adjust ; reset tab counter if value=0 PUSH AF LD A,(TABVAL) OR A JP Z,TABJ1 DEC A LD (TABVAL),A POP AF RET TABJ1:: ;reset tab counter LD A,TABSIZ LD (TABVAL),A POP AF RET ;------------------------------ ; NEWFIL::;%%-> Get the name of a new file and convert into the proper format ; to use for opening and reading it. ; CALL VCHR NEWFL:: CALL DINP10 ;load string LD A,(INNC) ;check char. count OR A ;count zero? JP Z,NEWF10 ; look for another input. ;-> move data LD C,A ;load counter LD DE,BUFF ;point to find buffer LD (DE),A ; save string length. INC DE LD HL,INCHAR ;point to string LD A,(HL) ; see if a help request only. CP '?' JP Z,HELP CALL MOVE ;copy string ; LD HL,FCB PUSH HL LD A,0 ; set for default drive read. LD (HL),A LD B,11 ; spaces to fill. LD A,20H ; with space. NEWF1:: INC HL LD (HL),A DEC B JP NZ,NEWF1 ; POP HL LD DE,BUFF LD A,(DE) ; no. of chars that were just read. LD C,A ; set up a counter. ; NEWF2:: INC DE ; next char in, INC HL ; out to fcb. LD A,(DE) CP '.' JP Z,NEWF4 ; skip and get ext. CALL UCASE ; convert to uppercase. LD (HL),A DEC C JP Z,NEWF8 ; JP NEWF2 ; NEWF4:: DEC C ; keep track. LD HL,FCB+8 ; 8th fn char. LD A,C AND 03 ; MAX. LD C,A NEWF5:: INC DE ; char following '.' INC HL LD A,(DE) AND 0FFH JP Z,NEWF8 ; done. CALL UCASE LD (HL),A DEC C JP Z,NEWF8 JP NEWF5 ; NEWF8:: LD HL,FCB+12 LD A,0 LD (HL),A JP LAB1 ; NEWF10:: LD DE,DONMSG JP EXMSG ; ;------------------------------ ; EXMSG:: CALL PRSTR FIN:: LD HL,(OLDSP) LD SP,HL LD A,(TMFLG) ; see if memory to top used. OR A JR NZ,FIN2 ; yes. RET ; FIN2:: JP 0000 ; exit thru warm boot. ; ENDMS:: DEFB ' $' ;------------------------------: ;### end of subroutines ### VIEW:: ;-> list out a page of text VIEW0:: LD A,0 ; disable output ot printer. LD (PFLG),A CALL VINP ;get input (loop until ready) ; VWW:: ;-> determine command CP CR JP Z,VIEW1 ;no digit, get next page CP '+' ;%% JP Z,VIEW1 CP '?' JP Z,HELP CP '-' JP Z,VW0 ;backup 1 page CP SPC JP Z,SPACE ;print 1 line CP '.' JP Z,SPACE CP 'L'-40H JP Z,RELOOK ;continue search AND 5FH ;make uppercase CP 'Q' JP Z,QUIT CP 'F' JP Z,SEARCH CP 'L' JP Z,VVW0 ;get line number CP 'E' JP Z,CLSCR ; and view next page CP 'T' JP Z,TOP CP 'B' JP Z,BOTTOM CP 'O' ;%% toggle line numbering off/on. JP Z,LONOFF CP 'N' ; new file requested? JP Z,NEWFIL CP 'P' ; print lines? JP Z,PRTPG CP 'S' ; scroll at a rate? JP Z,SCROL JP VIEW ;try input again ; CLSCR:: ;-> clear and print next page CALL CLS LD A,CR JP VWW ; LONOFF::LD A,(LINFLG) ;%% get the flag and toggle it. CPL LD (LINFLG),A ;%% CALL DECBIN ;display it to screen JP PW3A1 ;%%%% CHANGE THIS TO L CMD IN THE END? ; TOP:: ;-> jump to top of text CALL CLS LD HL,1 LD (LNREQ),HL JP ED ;%%% VIEW2 ; BOTTOM:: ;-> jump to bottom of text CALL CLS LD HL,(LASTLIN) ;last line LD (LNREQ),HL JP ED ; VW0:: ;-> back up a page LD HL,(LNREQ) ;get active line LD DE,35 ;& ;%%% take away lines - WAS 25 CALL SUB16 LD (LNREQ),HL ;save it JP C,VW1 ;value < 1 JP VW2 ; VW1:: LD HL,1 ;set line no. to 1 LD (LNREQ),HL ;save it VW2:: CALL CLS ;clear screen first JP ED ;%%% VIEW2 ; VVW0:: ;-> get line number CALL VCHR ;print 'L' CALL DINP10 ;get line number VIEW00:: LD A,(INNC) LD C,A LD HL,INCHAR ;point to line number VW3:: CALL DECBIN ;display it to screen EX DE,HL ; preserve hl. LD HL,(LASTLIN) ; test to see if past end. SBC HL,DE EX DE,HL JR NC,VW3A ; not past. LD DE,PEOT CALL PRSTR JP VIEW ; look for new cmd. VW3A:: PUSH HL ;save line # EX DE,HL ;in reg. DE LD HL,0 ;zero HL CALL COMP16 ;line # = 0? JP Z,VW4 POP HL ;restore orig. # LD DE,000AH ;& locate line no. at top of screen ADD HL,DE ;& instead of middle. LD (LNREQ),HL ;store in var. LD DE,11 ;&& CALL SUB16 ;&& JP ED ; do another page. ; VW4:: POP HL ;unload stack from VW3 module VIEW1:: ;look at next page LD HL,(LNREQ) LD DE,LNPPG-6 ;& WAS +18 before locate @ ln.;& line # + 15 ADD HL,DE LD (LNREQ),HL ;save modified # VIEW2:: ;-> view page JP ED ;do another page ; QUIT1:: CALL CRLF LD A,CR ;preset to CR for return JP VWW ; QUIT:: ;-> option to abandon text LD DE,QMSG CALL PRSTR CALL VINP ;get input CALL VCHR AND 5FH CP 'Y' ;really want to quit? JP NZ,QUIT1 ; AUTOLOAD:: JP NEWF10 ;%% SKIP AUTOLOAD, IT MESSES ; UP WHEN ZCPR2 HAS EXTERNAL ; COMMAND BUFFER. ;will load on exit LD HL,(1) ;calculate CCP from jump table base LD L,0 ; at loc. 0001h LD A,H SUB 16H LD H,A LD (CCP),HL ;save CCP address LD DE,7 ADD HL,DE ;adjust to CCP+7 (file count) ;-> reg. HL has required CCP position LD DE,FLOAD ;point to filename to load MCCP0:: LD A,(DE) ;move filename into CCP LD (HL),A CP 0 JP Z,MCCP1 ;zero means the terminator INC HL INC DE JP MCCP0 ; MCCP1:: LD HL,(CCP) ;load CCP base LD DE,88H ;reset command pointer ADD HL,DE ; at CCP + 88h LD A,8 LD (HL),A ;store value 8 ; LD A,(4) ;select current drive LD C,A ; at loc. 0004h LD HL,(CCP) ;get back CCP loc. JP (HL) ; and go there ; ;-> Auto-load file - enter count, filename, 0 ; Install your favorite directory program here FLOAD:: DEFB 2,'SD',0 ;<-- file to be loaded CCP:: DEFW 0 ; ;************************ ;-> routine to send lines to printer. ; used VVW0: as a starting point. ; PRTPG:: ;-> get line number CALL VCHR ;print 'P' LD A,(PGFLG) ; skip page display if last OR A ; cmd was 'find' or '^L'. JP Z,PRTPG1 ; LD DE,PNMSG ; announce page not found. CALL PRSTR JP VIEW ; PRTPG1::CALL DINP10 ;get line number PIEW00::LD A,(INNC) LD C,A LD HL,INCHAR ;point to line number LD A,(HL) ; see if '?' as request for CP '?' ; printing help page. JP Z,PPHLP PW3:: CALL DECBIN ;display it to screen LD A,0FFH LD (PFLG),A ; enable output to printer. PW3A1:: PUSH HL ;save line # (TOTAL). ; ;-> process as a range - from TOTAL1 to TOTAL. ; LD HL,(TOTAL1) ; see if first. LD A,L OR H JP NZ,PW3B ; use as first line of range. ; ;-> print the currently displayed page if true. ; POP HL ; get TOTAL back as 1st line. LD A,L ; if zero, no line entry made. OR H ; therefore, print whole file. JP NZ,PW3A ; print one page starting at hl. LD HL,(LSTART) ; fall thru to pw3a. ; ;-> add page length to print one page. ; PW3A:: PUSH HL ; starting line, bring back in DE. LD DE,LNCNR ; add to make a full page. LD (PGCNT),DE ; range. ADD HL,DE ; last line. POP DE ; starting line. JP PW3C ; ;-> process to get range. ; PW3B:: EX DE,HL ; DE = TOTAL1 as 1st. POP HL CALL SUB16 JP C,PRQ2 ; start > last, n.g. INC HL ; add 1 line. ---- worry about s=l? LD (PGCNT),HL ; LD HL,(TOTAL) ; get last. ; ;-> enter below if DE and HL are known. ; PW3C:: LD (LNREQ),HL LD (VLIN),DE ; start here. CALL LOCLINE CALL VAL1 JP VIEW ; ;-------------------------------- ; PRQ2:: LD A,0 ; disable printer output. LD (PFLG),A LD DE,PRQMSG CALL PRSTR JP VIEW ; look for another cmd. ; ;-> print help page ; PPHLP:: LD DE,MSG CALL LSTR JP VIEW ; done. ; ;************************ ; SEARCH:: ;-> find string CALL VCHR ;print 'F' CALL DINP10 ;load string LD A,(INNC) ;check char. count OR A ;count zero? JP Z,NOTFD LD (FCNT),A ;save string count ;-> move data LD C,A ;load counter LD DE,FBUF ;point to find buffer LD HL,INCHAR ;point to string CALL MOVE ;copy string ; LD HL,1 ;start search at line 1 LD (LNREQ),HL ; top of text LD HL,BUFF LD (SOL),HL ;start of line XOR A LD (ONSRCH),A ;clear on-search flag LD A,(FCNT) ;restore string count LD C,A LD DE,FBUF LD HL,BUFF SRCH1:: LD A,(HL) ;looking thru text AND 7FH ;strip msb (bit-7) CP CR ;EOL? JP Z,COUNTLN ;if so, count line CP 0 ;EOF? JP Z,NOTFD CP 1AH ;EOF? JP Z,NOTFD LD B,A ;move text byte to reg. B LD A,(DE) ;get search byte CP B ;compare the two JP Z,MATCH ;byte match? LD A,(ONSRCH) OR A JP Z,SRCH2 XOR A LD (ONSRCH),A LD A,(FCNT) LD C,A LD DE,FBUF LD HL,(SOS) SRCH2:: INC HL ;increment text pointer JP SRCH1 COUNTLN:: ;if here, at eol PUSH HL LD HL,(LNREQ) INC HL LD (LNREQ),HL POP HL INC HL LD (SOS),HL INC HL LD (SOL),HL JP SRCH1 MATCH:: ;if here, byte match LD A,(ONSRCH) OR A JP NZ,MATCH1 LD A,1 LD (ONSRCH),A LD (SOS),HL MATCH1:: DEC C JP Z,FOUND INC DE INC HL JP SRCH1 FOUND:: ;if here, complete string match LD A,0FFH ; set page not flag. LD (PGFLG),A CALL CRLF ;start new line LD HL,(LNREQ) ;current line # LD (LASTLN),HL ;last line string found INC HL ;aim at next line LD (VLIN),HL ;save here also LD (LSTART),HL DEC HL ;restore orig. line CALL BINDEC LD DE,COLAST CALL PRSTR LD HL,(SOL) ;get start of line ;-> new code CALL PRTLN ;display line ; FD2:: ;if here, must back up LD (EOL),HL INC HL ; need this to make right INC HL ; for SPACE routine. LD (SOL),HL LD A,CR FD3:: CALL VCHR FD4:: LD HL,(LNREQ) LD DE,-12 ADD HL,DE LD (LNREQ),HL CALL CRLF JP VIEW NOTFD:: LD DE,NFDMS ;'string not found' CALL PRSTR CALL CRLF JP VIEW ; ;-> Moved storage to end of program so it can all ; be reinitialized when getting a new file. ; RELOOK:: ;-> continue search for string ; found by F command LD HL,(LASTLN) ;get last line string found LD (LNREQ),HL ;make active LD HL,(SOS) ;location of end of string JP SRCH1 ;start processing ; ;-> continuous scroll until any letter except space ; or numerals. Space increases scrolling to auto- ; key rate, numerals control speed, 0 = slowest, ; 9 = fastest. SCROL:: CALL SPACER ; do it once. CALL VINPST ; see if anything from keys. JP Z,SCROL6 ; nothing ready. CALL VINPY ; yes, get it. CP ':' ; 9 or less? JP NC,VIEW ; no, stop scroll. CP '0' ; 0 to 9? JP C,VIEW ; no. SUB 3BH ; convert, 0 to 9 CPL ; become 10 to 1. LD (SCRDLY),A SCROL6::CALL SCD ; scroll delay. JR SCROL ; continue on. ; ;-> scroll delay rate. SCD:: LD A,(SCRDLY) ; get the base. PUSH BC PUSH DE LD D,A SUB 9 ; get orig. value. CPL LD E,A ; value x6. ADD A,A ADD A,E ADD A,A LD E,A LD A,39H ; long delay base (PICKED FOR A 4MHZ SYSTEM. SUB E ; now set final delay/cycle. LD E,A ; number of loops. SCD2:: LD B,D ; length/loop. LD C,0 SCD4:: DEC BC LD A,B OR C JR NZ,SCD4 SCD6:: LD B,D LD C,0 SCD8:: DEC BC LD A,B OR C JR NZ,SCD8 DEC E JR NZ,SCD2 POP DE POP BC RET ; ; SPACE:: ;-> space bar - find more strings ; adjust new line # and find memory CALL SPACER ; call for a one line scroll. JP VIEW ; done. ; ;-> this is the original one line space routine. ; SPACER::LD A,0 ; clear page not flag. LD (PGFLG),A LD HL,(LNREQ) ;get line # INC HL ;increment EX DE,HL ; preserve hl. LD HL,(LASTLIN) ; test to see if past end. SBC HL,DE EX DE,HL JR NC,SPC1B ; not past. LD DE,PASTLN CALL PRSTR RET SPC1B:: LD (LNREQ),HL ;save it LD HL,(VLIN) ;get current line number ; LD A,(LINFLG) ;%% see if line no. CP 0FFH ;%% is requested. JP Z,SPC2 ;%% no. ; ; CALL BINDEC ;print line number LD DE,COLON ; and colon/space CALL PRSTR SPC2:: LD HL,(SOL) ;get last start of line CALL PRTLN ;print line PUSH HL LD HL,(VLIN) INC HL ;adjust pointer LD (VLIN),HL LD HL,(LSTART) ;%% INC HL LD (LSTART),HL ;%% POP HL INC HL INC HL ;point to SOL next LD (SOL),HL RET ; LOCLINE:: ;-> locate line, starting from buff ; returns with HL at SOL LD HL,BUFF ;start of text LD DE,1 ;begin with line 1 LOC0:: PUSH HL LD HL,(VLIN) LD (LSTART),HL CALL COMP16 ;match? POP HL RET Z ;if here, isn't the line - start looking LOC1:: LD A,(HL) AND 7FH ;strip bit 7 CP CR JP Z,LOC2 CP 0 ;EOF? RET Z CP 1AH ;CP/M EOF RET Z INC HL JP LOC1 LOC2:: ;if here, found CR (EOL) INC HL ;move to lf INC HL ;move to sol INC DE ;increment line count JP LOC0 PAGELN:: ;-> determine page line ; returns with VLIN set to proper value LD DE,10 ;&set line to middle of page CALL SUB16 JP NC,PLN2 PLN0:: LD HL,1 PLN1:: LD (VLIN),HL RET PLN2:: PUSH HL LD DE,0 CALL COMP16 POP HL JP Z,PLN0 JP PLN1 ; HELP:: ;list out edit commands CALL CLS LD DE,MSG CALL PRSTR JP VIEW ; ;%%->Convert lower to uppercase, value in A. UCASE:: CP 'a' JR C,UCDON CP 'z'+1 JR NC,UCDON SUB 'a'-'A' UCDON:: RET ; SIGNON:: DEFB 'Line Display v' DEFB VERS/100+'0',VERS MOD 100/10+'0','.' DEFB VERS MOD 10+'0' DEFB '$' NOFIL:: DEFB ' <-- Must include filename',CR,LF,'$' WAITA:: DEFB CR,LF,'File $' WAITB:: DEFB ' ',' now loading sectors: $' NOFN1:: DEFB ' Disk file $' NOFN2:: DEFB ' ',' not found on disk',CR,LF,'$' REFIL:: DEFB 'Make another entry, ? for help or to quit to cp/m ? $' DONMSG::DEFB ' EXITTING.........',CR,LF,'$' PNMSG:: DEFB ' Page of display, not currently defined....',CR,LF,'$' PRQMSG::DEFB ' Inadequate range, reenter or new command...',CR,LF,'$' QMSG:: DEFB CR,LF,' Sure you want to quit? $' NFDMS:: DEFB CR,LF,'---> string not found $' ;-> the follow message uses imbedded code for ; blinking and underlining. MSG:: DEFB 'Line Display, Version ' DEFB VERS/100+'0',VERS MOD 100/10+'0','.' DEFB VERS MOD 10+'0' DEFB ' (Generic) 7-19-86' DEFB ' Jon Lindsay/ Joe Field ' DEFB CR,LF DEFB ' Features: 1) viewing page ' DEFB 'by page - forward/backward',CR,LF DEFB ' 2) jump to specific line',CR,LF DEFB ' 3) string search',CR,LF DEFB ' 4) print current page or specific lines' DEFB CR,LF DEFB ' Input commands:',CR,LF DEFB ' RETURN or + = forward 1 page',CR,LF DEFB ' - = backup 1 page',CR,LF DEFB ' space bar or . = forward 1 line',CR,LF DEFB ' S = auto scroll, 0 (slow) to 9 (fast), ' DEFB 'others cancel.',CR,LF DEFB ' Lnnnn = line number. Displays from line nnnn,' DEFB ' down one page.' DEFB CR,LF DEFB ' T = top of text',CR,LF DEFB ' B = bottom of text',CR,LF DEFB ' E = erase screen and advance 1 page',CR,LF DEFB ' Fstr = Find string, e.g., fHello' DEFB ' means locate',CR,LF DEFB ' string "Hello." U/L case matters!',CR,LF DEFB ' control-L = search next occurrence of string',CR,LF DEFB ' O = toggle line numbering on/off',CR,LF DEFB ' P cr = send current page to printer,',CR,LF DEFB ' Pn = page starting at n, Pn m = n to m' DEFB ', n = ? prints help.' DEFB CR,LF DEFB ' Nfn.ext = load New file; Ncr = quit, return to CP/M' DEFB CR,LF DEFB ' Q = quit and return to CP/M',CR,LF DEFB ' ? = print this message',CR,LF,'$' MEMFUL:: DEFB 'Only partial file transfer' DEFB ' due to memory size...',CR,LF,'$' PASTLN::DEFB '---> last line...',CR,LF,BELL,'$' PEOT:: DEFB '---> past end of text area...',CR,LF,BELL,'$' WFCB:: DEFS 33 INMX:: DEFB 30 TOTAL:: DEFW 0 TOTAL1::DEFW 0 TOTAL2::DEFW 0 SCRDLY::DEFB 5 ; initial scroll rate. TMFLG:: DEFB 0 ; ;-------------------------------- ; ;-> all below here get zero'd out at initialization. ; TDMA:: DEFW 0 ; put all below here. PFLG:: DEFB 0 ; 0 = crt output, 1 = printer. CURPOS::DEFB 0 SOT:: DEFW 0 EOT:: DEFW 0 EOL:: DEFW 0 TOPMEM::DEFW 0 ;%% TOP OF MEMORY (CALCULATED). PRECCP::DEFW 0 ; MEMORY BEFORE CCP. LINFLG::DEFB 0 ;%% LINE FLAG ON IF 0, OFF IF FF. ; ; moved the following to here. ; easier to find. ; ONSRCH::DEFB 0 ;on search SOS:: DEFW 0 ;start of string LASTLN::DEFW 0 ;line # of last string FBUF:: DEFS 30 ;string can be 30 char. FCNT:: DEFB 0 ;actual find buffer counter INNC:: DEFB 0 INCHAR::DEFB 0 DEFS 30 ;space for 30, must follow INCHAR. PGFLG:: DEFB 0 ; 0ffh if last cmd = find or ^L. LSTART::DEFW 0 ; beginning of current display. VLIN:: DEFW 0 ; line to begin display, then ; last displayed+1. LNREQ:: DEFW 1 ;current line number PGCNT:: DEFW 0 ;page line counter SOL:: DEFW 0 ;%% last moved. LASTLIN:: DEFW 0 BUFF EQU $ ;file loaded starting here END