* * PROGRAM NAME: HELP2 * AUTHOR: RICHARD CONN * DATE: 23 MAY 83 * VERSION: 4.1 * PREVIOUS VERSIONS: 4.0 (14 JAN 83), 3.2 (6 JAN 83) * PREVIOUS VERSIONS: 3.1 (8 DEC 82), 3.0 (11 OCT 82), 2.0 (30 OCT 81) * PREVIOUS VERSIONS: 1.8 (18 OCT 81), 1.7 (10 SEP 81), 1.6 (9 SEP 81) * PREVIOUS VERSIONS: 1.5 (9 SEP 81), 1.4 (8 SEP 81), 1.3 (8 SEP 81) * PREVIOUS VERSIONS: 1.2 (7 SEP 81), 1.1 (6 OCT 80), 1.0 (18 NOV 79) * NOTE: FOR USE WITH ZCPR 2.0 AND LATER * VERS EQU 41 ; ; This program is Copyright (c) 1982, 1983 by Richard Conn ; All Rights Reserved ; ; ZCPR2 and its utilities, including this one, are released ; to the public domain. Anyone who wishes to USE them may do so with ; no strings attached. The author assumes no responsibility or ; liability for the use of ZCPR2 and its utilities. ; ; The author, Richard Conn, has sole rights to this program. ; ZCPR2 and its utilities may not be sold without the express, ; written permission of the author. ; ; ; HELP supports an online documentation system under ZCPR2. Refer ; to the file HELP.HLP for more details. ; ; ; CP/M Constants ; FALSE EQU 0 TRUE EQU NOT FALSE UDFLAG EQU 4 ; ADDRESS OF USER/DISK FLAG BDOS EQU 5 ; ADDRESS OF BDOS ENTRY POINT FCB EQU 5CH ; ADDRESS OF FILE CONTROL BLOCK BUFF EQU 80H ; ADDRESS OF DMA BUFFER CR EQU 0DH ; LF EQU 0AH ; FF EQU 'L'-40H ; CTRL-L = FORM FEED CTRLZ EQU 'Z'-40H ; CTRL-Z CTRLC EQU 'C'-40H ; CTRL-C ; ; HELP Control Characters ; SECT$CHAR EQU ':' ; DEFINED TO BE COLON BACKUP$CHAR EQU 'L' ; BACK UP TO PREVIOUS FRAME CHAR START$CHAR EQU 'S' ; JUMP TO START OF INFORMATION CHAR MENU$CHAR EQU 'M' ; CHAR TO ABORT TO MENU CPM$ABORT$CHAR EQU CTRLC ; CHAR TO EXIT LEVEL$RET$CHAR EQU '^' ; RETURN TO PREVIOUS HELP LEVEL ROOT$CHAR EQU '.' ; RETURN TO ROOT OF HELP PRINT$CHAR EQU 'P' ; PRINT CURRENT INFORMATION SECTION ; ; Lines/Screen on CRT ; LINES$PER$SCREEN EQU 24 ; ASSUME 24 LINES/SCREEN ; ; Number of File Names per Line ; NAMES$PER$LINE EQU 6 ; 6 NAMES (SPACE = 6*11 COLS) ; ; Set this to TRUE if all files must be of type HLP ; FORCE$HLP EQU TRUE ; TRUE IF FILES MUST BE OF TYPE HLP ; ; Number of Nodes (Levels) in Help File Tree ; HELP$MAX EQU 10 ; DEFAULT = 10 (SPACE=11*HELP$MAX) ; ; MACROS TO PROVIDE Z80 EXTENSIONS ; MACROS INCLUDE: ; $-MACRO ;FIRST TURN OFF THE EXPANSIONS ; ; JR - JUMP RELATIVE ; JRC - JUMP RELATIVE IF CARRY ; JRNC - JUMP RELATIVE IF NO CARRY ; JRZ - JUMP RELATIVE IF ZERO ; JRNZ - JUMP RELATIVE IF NO ZERO ; DJNZ - DECREMENT B AND JUMP RELATIVE IF NO ZERO ; LDIR - MOV @HL TO @DE FOR COUNT IN BC ; LXXD - LOAD DOUBLE REG DIRECT ; SXXD - STORE DOUBLE REG DIRECT ; ; ; ; @GENDD MACRO USED FOR CHECKING AND GENERATING ; 8-BIT JUMP RELATIVE DISPLACEMENTS ; @GENDD MACRO ?DD ;;USED FOR CHECKING RANGE OF 8-BIT DISPLACEMENTS IF (?DD GT 7FH) AND (?DD LT 0FF80H) DB 100H ;Displacement Range Error on Jump Relative ELSE DB ?DD ENDIF ENDM ; ; ; Z80 MACRO EXTENSIONS ; JR MACRO ?N ;;JUMP RELATIVE DB 18H @GENDD ?N-$-1 ENDM ; JRC MACRO ?N ;;JUMP RELATIVE ON CARRY DB 38H @GENDD ?N-$-1 ENDM ; JRNC MACRO ?N ;;JUMP RELATIVE ON NO CARRY DB 30H @GENDD ?N-$-1 ENDM ; JRZ MACRO ?N ;;JUMP RELATIVE ON ZERO DB 28H @GENDD ?N-$-1 ENDM ; JRNZ MACRO ?N ;;JUMP RELATIVE ON NO ZERO DB 20H @GENDD ?N-$-1 ENDM ; DJNZ MACRO ?N ;;DECREMENT B AND JUMP RELATIVE ON NO ZERO DB 10H @GENDD ?N-$-1 ENDM ; LDIR MACRO ;;LDIR DB 0EDH,0B0H ENDM ; LDED MACRO ?N ;;LOAD DE DIRECT DB 0EDH,05BH DW ?N ENDM ; LBCD MACRO ?N ;;LOAD BC DIRECT DB 0EDH,4BH DW ?N ENDM ; SDED MACRO ?N ;;STORE DE DIRECT DB 0EDH,53H DW ?N ENDM ; SBCD MACRO ?N ;;STORE BC DIRECT DB 0EDH,43H DW ?N ENDM ; ; END OF Z80 MACRO EXTENSIONS ; ORG 100H ; ; Branch to Start of Program ; jmp start ; ;****************************************************************** ; ; SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format ; ; This data block precisely defines the data format for ; initial features of a ZCPR2 system which are required for proper ; initialization of the ZCPR2-Specific Routines in SYSLIB. ; ; ; EXTERNAL PATH DATA ; EPAVAIL: DB 0FFH ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES) EPADR: DW 40H ; ADDRESS OF EXTERNAL PATH IF AVAILABLE ; ; INTERNAL PATH DATA ; INTPATH: DB 0,0 ; DISK, USER FOR FIRST PATH ELEMENT ; DISK = 1 FOR A, '$' FOR CURRENT ; USER = NUMBER, '$' FOR CURRENT DB 0,0 DB 0,0 DB 0,0 DB 0,0 DB 0,0 DB 0,0 DB 0,0 ; DISK, USER FOR 8TH PATH ELEMENT DB 0 ; END OF PATH ; ; MULTIPLE COMMAND LINE BUFFER DATA ; MCAVAIL: DB 0FFH ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE? MCADR: DW 0FF00H ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE ; ; DISK/USER LIMITS ; MDISK: DB 4 ; MAXIMUM NUMBER OF DISKS MUSER: DB 31 ; MAXIMUM USER NUMBER ; ; FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK ; DOK: DB 0FFH ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES) UOK: DB 0FFH ; ALLOW USER CHANGE? (0=NO, 0FFH=YES) ; ; PRIVILEGED USER DATA ; PUSER: DB 10 ; BEGINNING OF PRIVILEGED USER AREAS PPASS: DB 'chdir',0 ; PASSWORD FOR MOVING INTO PRIV USER AREAS DS 41-($-PPASS) ; 40 CHARS MAX IN BUFFER + 1 for ending NULL ; ; CURRENT USER/DISK INDICATOR ; CINDIC: DB '$' ; USUAL VALUE (FOR PATH EXPRESSIONS) ; ; DMA ADDRESS FOR DISK TRANSFERS ; DMADR: DW 80H ; TBUFF AREA ; ; NAMED DIRECTORY INFORMATION ; NDRADR: DW 00000H ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY NDNAMES: DB 64 ; MAX NUMBER OF DIRECTORY NAMES DNFILE: DB 'NAMES ' ; NAME OF DISK NAME FILE DB 'DIR' ; TYPE OF DISK NAME FILE ; ; REQUIREMENTS FLAGS ; EPREQD: DB 0FFH ; EXTERNAL PATH? MCREQD: DB 000H ; MULTIPLE COMMAND LINE? MXREQD: DB 000H ; MAX USER/DISK? UDREQD: DB 000H ; ALLOW USER/DISK CHANGE? PUREQD: DB 000H ; PRIVILEGED USER? CDREQD: DB 000H ; CURRENT INDIC AND DMA? NDREQD: DB 000H ; NAMED DIRECTORIES? Z2CLASS: DB 5 ; CLASS 5 DB 'ZCPR2' DS 10 ; RESERVED ; ; END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA ; ;****************************************************************** ; ; ; DEFAULT FILE NAME ; DEFFN: DB 'HELP ' DEFTYP: DB 'HLP' ; ; Start of Program ; START: LXI H,0 ; GET SP DAD SP SHLD STACK LXI SP,STACK ; NEW STACK MVI E,0FFH ; GET CURRENT USER NUMBER MVI C,32 CALL BDOS STA CUR$USER ; CURRENT USER NUMBER LDA BDOS+2 ; BASE PAGE OF BDOS SUI 10 ; 2K + 2 PAGES STA TPA$END XRA A ; A=0 STA DFFLG ; TURN OFF DEFAULT FILE FLAG STA HELP$LEVEL ; SET HELP LEVEL TO 0 (NO RETURN FILE) LXI D,HELPMS ; PRINT OPENING MSG CALL PRINT$MESSAGE LXI H,FCB+1 ; CHECK FOR FILE NAME MOV A,M CPI ' ' ; NONE? JRNZ START1 * INSERT 'HELP.HLP' INTO FCB OR CLEAR FCB LXI D,DEFFN ; PT TO DEFAULT NAME MVI B,11 ; 11 BYTES XCHG CALL MOVE ; MOVE (HL) TO (DE) FOR (B) BYTES MVI A,1 ; TURN ON DEFAULT FILE FLAG STA DFFLG * START/RESTART HELP PROGRAM (START ON INITIAL ENTRY, RESTART ON NODE LOAD) START1: LXI SP,STACK ; SET STACK POINTER * CLEAR NON-NAME/TYPE BYTES IN FCB LXI H,FCB ; INITIAL ZERO MVI M,0 ; STORE 0 FOR DRIVE (CURRENT LOGGED-IN) LXI D,12 ; SKIP TO EXTENT DAD D MVI B,24 ; FILL 24 BYTES FCB$FILL: MVI M,0 ; ZERO FILL INX H ; PT TO NEXT DJNZ FCB$FILL * CHECK FOR WILD CARDS IN FILE NAME -- ERROR IF SO LXI H,FCB+1 ; PT TO FIRST BYTE OF FILE NAME MVI B,11 ; 11 BYTES FCB$WILD$CK: MOV A,M ; GET BYTE ANI 7FH ; MASK CPI '?' ; WILD? JRZ FCB$WILD$ERROR INX H ; PT TO NEXT DJNZ FCB$WILD$CK * CHECK FOR FILE TYPE LXI H,FCB+9 ; CHECK FOR FILE TYPE IF NOT FORCE$HLP ; IF FILE TYPE MAY NOT BE HLP MOV A,M ; CHECK FOR FILE TYPE SPECIFIED CPI ' ' ; NONE? JRNZ START2 ENDIF * PLACE DEFAULT FILE TYPE OF '.HLP' IN FCB DEFAULT$EXT: LXI D,DEFTYP ; DEFAULT FILE TYPE MVI B,3 XCHG CALL MOVE ; MOVE (HL) TO (DE) FOR (B) BYTES * OPEN FILE START2: LDA DFFLG ; CHECK FOR DEFAULT ORA A ; 0=NO JNZ HELP$DEF ; DISPLAY DEFAULT HELP INFO WITH FILE NAMES LXI H,INTPATH ; SET BASE ADDRESS OF PATH LDA EPAVAIL ; EXTERNAL PATH AVAILABLE ORA A ; 0=NO JRZ START2A LHLD EPADR ; GET ADDRESS OF EXTERNAL PATH START2A: LXI D,FCB ; PT TO FCB CALL FNDFILE ; SEARCH FOR FILE JNZ START3 ; FILE FOUND, SO PROCESS LDA EPAVAIL ; SEARCH ALONG EXTERNAL PATH? ORA A ; 0=NO JRZ START2B LXI H,INTPATH ; SELECT INTERNAL PATH THEN LXI D,FCB ; PT TO FCB CALL FNDFILE ; SEARCH JNZ START3 ; FILE FOUND * FILE NOT FOUND -- FATAL ERROR START2B: LXI D,ERR1 ; FILE NOT FOUND CALL PRINT$MESSAGE JMP HELP$EXIT * FILE CONTAINS WILD CARDS -- FATAL ERROR FCB$WILD$ERROR: LXI D,WILD$ERR ; WILD CARD CALL PRINT$MESSAGE JMP HELP$EXIT * * DISPLAY DEFAULT HELP FILE INFORMATION * HELP$DEF: LXI D,HELP$DEF$MSG ; PRINT MESSAGE CALL PRINT$MESSAGE CALL SET$COUNT ; SET COUNTER CALL RESET$SYSTEM ; RETURN HOME CALL PRINT$HELP$FILES ; PRINT HELP FILES AT HOME LDA EPAVAIL ; EXTERNAL PATH? LHLD EPADR ; EXTERNAL PATH ADDRESS ORA A ; 0=NO EXTERNAL PATH CNZ HDFF1 CALL RESET$SYSTEM ; RETURN HOME LXI H,INTPATH ; FOLLOW INTERNAL PATH CALL HDFF1 ; SEARCH IT CALL RESET$SYSTEM ; RESET CALLING DISK/USER NUMBER LXI D,HELP$EDEF$MSG ; PRINT END MESSAGE CALL PRINT$MESSAGE CALL CHAR$IN ; GET ANY CHAR FOR RESPONSE CPI CTRLC ; ABORT? JZ HELP$EXIT XRA A ; TURN OFF DEFAULT STA DFFLG LXI H,DEFFN ; SET DEFAULT FILE NAME LXI D,FCB+1 MVI B,11 ; 11 BYTES CALL MOVE JMP START2 ; PROCESS DEFAULT HELP FILE ; ; MAIN SEARCH LOOP ; HDFF1: LDA CINDIC ;GET CURRENT DISK INDICATOR MOV B,A ;... IN B MOV A,M ;GET DRIVE ANI 7FH ;MASK MSB ORA A ;0=DONE=COMMAND NOT FOUND RZ ;END OF PATH? ; ; LOOK FOR COMMAND IN DIRECTORY PTED TO BY HL; DRIVE IN A ; CMP B JRNZ HDFF2 ;SKIP DEFAULT DRIVE SELECTION IF SO LDA UDFLAG ;GET DEFAULT USER/DISK ANI 0FH ;MASK FOR DEFAULT DISK INR A ;PREP FOR FOLLOWING DCR A HDFF2: DCR A ;ADJUST PATH 1 TO 0 FOR A, ETC MOV E,A ;DISK NUMBER IN E MVI C,14 ;SELECT DISK FCT CALL BENTRY ;SELECT DRIVE INX H ;PT TO USER NUMBER MOV A,M ;GET USER NUMBER INX H ;PT TO NEXT PATH ELEMENT ANI 7FH ;MASK OUT MSB CMP B JRNZ HDFF3 ;DO NOT SELECT CURRENT USER IF SO LDA CUR$USER ;GET ORIGINAL USER NUMBER HDFF3: MOV E,A ;SELECT USER MVI C,32 CALL BENTRY PUSH H ;SAVE PATH PTR CALL PRINT$HELP$FILES POP H ;GET PATH PTR JR HDFF1 * * SET FILE NAME COUNTER * SET$COUNT: MVI A,NAMES$PER$LINE ; NUMBER OF FILE NAMES/LINE STA NAME$COUNT RET * * PRINT NAMES OF HELP FILES * PRINT$HELP$FILES: LXI H,FCB ; MAKE FCB = *.HLP MVI M,0 ; BEGINNING 0 FOR DEFAULT DISK MVI B,8 ; FILL 8 ?'S INX H ; PT TO FIRST CHAR PHF1: MVI M,'?' ; '?' FILL INX H ; PT TO NEXT DJNZ PHF1 LXI D,DEFTYP ; COPY DEFAULT FILE TYPE MVI B,3 ; 3 BYTES XCHG ; EXCHANGE CALL MOVE ; COPY XCHG ; RESTORE PTR MVI B,24 ; FILL REST WITH 0'S PHF2: MVI M,0 ; 0 FILL INX H ; PT TO NEXT DJNZ PHF2 * SEARCH FOR FIRST FILE LXI D,FCB ; PT TO FCB MVI C,17 ; SEARCH FOR FIRST CALL BDOS CPI 0FFH ; NONE? RZ ; DONE IF SO * PRINT CURRENT AND SEARCH FOR NEXT PHF3: CALL PRINT$HFN ; PRINT HELP FILE NAME LXI D,FCB ; PT TO FCB MVI C,18 ; SEARCH FOR NEXT CALL BDOS CPI 0FFH ; DONE? JRNZ PHF3 RET * * PRINT NAME OF FILE WHOSE BUFF OFFSET IS IN A * PRINT$HFN: RRC ; A=A*32 RRC RRC ; RATHER THAN 5 LEFT, I DO 3 RIGHT (NEAT, HUH?) ANI 60H ; MASK ALL BUT INTERESTING PART LXI H,BUFF ; PT TO BUFFER ADD L ; PT TO ENTRY MOV L,A MOV A,H ACI 0 MOV H,A ; HL PTS TO ENTRY INX H ; HL PTS TO HELP FILE NAME MVI B,8 ; 8 CHARS PHFN1: MOV A,M ; GET CHAR ANI 7FH ; MASK INX H ; PT TO NEXT CALL CHAR$OUT ; PRINT IT DJNZ PHFN1 MVI A,' ' ; TRAILING SPACES CALL CHAR$OUT ; 3 OF THEM CALL CHAR$OUT CALL CHAR$OUT LDA NAME$COUNT ; COUNT DOWN DCR A STA NAME$COUNT RNZ CALL SET$COUNT ; RESET COUNT CALL CRLF ; NEW LINE RET * * LOAD HELP FILE INFORMATION * START3: LXI D,FCB ; OPEN FILE MVI C,15 ; BDOS FILE OPEN CALL BDOS LXI H,HELP$BUF ; PT TO BUFFER SHLD NEXT$ADR ; SET PTR * READ RECORDS UNTIL EOF START4: CALL READ$RECORD ; READ INFO JRZ START4 ; NOT DONE IF ZERO RETURN LXI D,FCB ; CLOSE FILE MVI C,16 ; CLOSE CALL BDOS CALL RESET$SYSTEM ; RESTORE CURRENT DISK AND USER IF CHANGED * * START OF HELP PROGRAM * HELP: LXI SP,STACK ; RESET STACK MVI A,0 ; SET NO FRAME STA FRAME$NUMBER LXI H,HELP$BUF ; PT TO BUFFER MOV A,M ; NO HEADER SECTION? ANI 7FH ; MASK OUT MSB CPI SECT$CHAR JRNZ HELP1 ; HEADER SECTION EXISTS CALL PRINT$INFO ; PRINT HELP INFO PTED TO BY HL LDA HELP$LEVEL ; CHECK TO SEE IF WE ARE NOT AT LEVEL 0 ORA A ; 0=LEVEL 0 JRZ HELP$EXIT ; ABORT IF SO JMP LEVEL$RETURN ; GO TO PREVIOUS LEVEL IF NOT * EXIT POINT FOR ANY EXIT FROM THE REST OF THE HELP PROGRAM HELP$EXIT: CALL RESET$SYSTEM ; RESET CALLING DISK/USER NUMBER LHLD STACK ; GET CP/M SP SPHL RET ; DONE * PRINT HEADER INFORMATION AND SELECT AN OPTION HELP1: CALL PRINT$HEADER ; PRINT HEADER PUSH B ; SAVE C (NUMBER OF VALID SELECTIONS) CALL CRLF1 ; NEW LINE CALL PR$LEVEL ; PRINT LEVEL NUMBER LXI D,PROMPT1$MESSAGE ; PRINT PROMPT CALL PRINT$MESSAGE LXI D,PROMPT2$MESSAGE ; LEVEL COMMAND LDA HELP$LEVEL ; CURRENT LEVEL = 0? ORA A ; SET FLAGS JRZ HELP1A CALL PRINT$MESSAGE HELP1A: LXI D,PROMPT3$MESSAGE CALL PRINT$MESSAGE POP B ; GET C CALL CHAR$IN ; GET RESPONSE CPI CTRLC ; EXIT JRZ HELP$EXIT CPI ROOT$CHAR ; GO TO ROOT JZ GO$ROOT CPI LEVEL$RET$CHAR ; RETURN TO PREVIOUS LEVEL JZ LEVEL$RETURN PUSH PSW ; SAVE CHAR CALL CRLF1 POP PSW ; GET CHAR SUI 'A'-1 ; ADJUST FOR COUNT MOV B,A ; SAVE COUNT JRZ BAD$RESPONSE JRNC HELP2 * INVALID RESPONSE BAD$RESPONSE: LXI D,ERR2 ; INVALID RESPONSE CALL PRINT$MESSAGE JR HELP1 * VALID RESPONSE -- LOOK FOR AND PRINT INFORMATION SECTION HELP2: INR C ; 1 MORE THAN NUMBER OF POSSIBLE SELECTIONS CMP C ; GREATER THAN NUMBER OF POSSIBLE SELECTIONS? JRNC BAD$RESPONSE LHLD FIRST$ENTRY ; GET PTR TO FIRST ENTRY * PRINT INFORMATION WHEN COUNT IS ZERO HELP3: DJNZ HELP4 CALL PRINT$INFO ; PRINT INFO PTED TO BY HL JR HELP1 * LOCATE NEXT INFORMATION SECTION HELP4: MOV A,M ; ? ANI 7FH ; MASK OUT MSB INX H ; PT TO NEXT BYTE CPI CTRLZ JZ HELP$ERR ; HELP FILE FORMAT ERROR CPI LF ; LINE FEED (WS FILE)? JRZ HELP5 CPI CR ; ? JRNZ HELP4 INX H ; 1ST BYTE OF NEXT LINE HELP5: MOV A,M ; GET CHAR ANI 7FH ; MASK OUT MSB CPI SECT$CHAR ; NEW SECTION? JRZ HELP3 ; CONTINUE LOOP IF SO CPI CTRLZ ; EOF? JRNZ HELP4 ; CONTINUE IF NOT * ERROR -- REACHED END OF HELP FILE HELP$ERR: LXI D,ERR3 ; FORMAT ERROR CALL PRINT$MESSAGE JMP HELP1 ********************************************************* * * * HELP SUPPORT ROUTINE SECTION * * * ********************************************************* * * RESTORE CURRENT DISK AND CURRENT USER * RESET$SYSTEM: LDA UDFLAG ; GET DISK ANI 0FH ; GET DISK NUMBER MOV E,A ; DISK IN E MVI C,14 ; SELECT DISK CALL BDOS LDA CUR$USER ; SET USER MOV E,A ; USER IN E MVI C,32 ; SET USER CODE CALL BDOS RET * * FNDFILE -- LOOK FOR FILE ALONG ZCPR2 PATH * INPUT PARAMETERS: HL = BASE ADDRESS OF PATH, DE = PTR TO FCB OF FILE * OUTPUT PARAMETERS: A=0 AND ZERO FLAG SET IF NOT FOUND, NZ IF FOUND * FNDFILE: SHLD PATH ;SAVE PATH BASE ADDRESS MVI C,17 ;SEARCH FOR FIRST CALL BENTRY ;LOOK FOR FILE INR A ;SET FLAG JRNZ FF5 ;FOUND IT -- RETURN FOUND FLAG XCHG ;HL=FCB PTR SHLD FCBPTR ;SAVE IT LHLD PATH ;PT TO PATH FOR FAILURE POSSIBILITY ; ; MAIN SEARCH LOOP ; FF1: LDA CINDIC ;GET CURRENT USER/DISK INDICATOR MOV B,A ;... IN B MOV A,M ;GET DRIVE ANI 7FH ;MASK MSB ORA A ;0=DONE=COMMAND NOT FOUND JRNZ FF2 ;NO ERROR ABORT? ; ; FILE NOT FOUND ERROR ; XRA A ;ZERO FLAG MEANS NOT FOUND RET ; ; LOOK FOR COMMAND IN DIRECTORY PTED TO BY HL; DRIVE IN A ; FF2: CMP B ;CURRENT DISK? JRNZ FF3 ;SKIP DEFAULT DRIVE SELECTION IF SO LDA UDFLAG ;GET DEFAULT USER/DISK ANI 0FH ;MASK FOR DEFAULT DISK INR A ;PREP FOR FOLLOWING DCR A FF3: DCR A ;ADJUST PATH 1 TO 0 FOR A, ETC MOV E,A ;DISK NUMBER IN E MVI C,14 ;SELECT DISK FCT CALL BENTRY ;SELECT DRIVE INX H ;PT TO USER NUMBER MOV A,M ;GET USER NUMBER ANI 7FH ;MASK OUT MSB INX H ;PT TO NEXT ENTRY IN PATH CMP B ;CURRENT USER? JRNZ FF4 ;DO NOT SELECT CURRENT USER IF SO LDA CUR$USER ;GET ORIGINAL USER NUMBER FF4: MOV E,A ;SELECT USER MVI C,32 CALL BENTRY XCHG ;SAVE PTR TO NEXT PATH ELEMENT IN DE LHLD FCBPTR ;GET PTR TO FCB XCHG ;... IN DE, PATH PTR IN HL MVI C,17 ;SEARCH FOR FIRST CALL BENTRY ;LOOK FOR FILE INR A ;SET FLAG JRZ FF1 ;CONTINUE PATH SEARCH IF SEARCH FAILED ; ; FILE FOUND -- PERFORM SYSTEM TEST AND PROCEED IF APPROVED ; FF5: MVI A,0FFH ;SET OK RETURN ORA A RET ; ; BDOS ROUTINE ; BENTRY: PUSH H ;SAVE REGS PUSH D PUSH B CALL BDOS POP B ;GET REGS POP D POP H RET * BUFFERS FCBPTR: DS 2 ;POINTER TO FCB FOR FILE SEARCH PATH: DS 2 ;BASE ADDRESS OF PATH * * INPUT CHAR; CHAR IS IN A * CHAR$IN: PUSH B ! PUSH D ! PUSH H MVI C,1 ; READ CHAR CALL BDOS POP H ! POP D ! POP B PUSH PSW ; SAVE CHAR CALL CRLF1 POP PSW ; RESTORE CHAR * * CAPITALIZE CHAR IN A * CAPS: ANI 7FH ; MASK OUT MSB CPI 61H ; LESS THAN SMALL A? RC CPI 7BH ; LESS THAN LEFT BRACE? RNC ANI 5FH ; CAPITALIZE RET * * PRINT CHAR IN A ON CON: * CHAR$OUT: PUSH PSW ! PUSH B ! PUSH D ! PUSH H MVI C,2 ; WRITE MOV E,A ; CHAR IN E CALL BDOS POP H ! POP D ! POP B ! POP PSW RET * * PRINT ERROR MSG PTED TO BY DE; ENDS IN '$' * PRINT$MESSAGE: PUSH B ! PUSH D ! PUSH H MVI C,9 ; PRINT BUFFER CALL BDOS POP H ! POP D ! POP B RET * * MOVE BYTES PTED TO BY HL TO AREA PTED TO BY DE; B BYTES TO MOVE * MOVE: MOV A,M ; GET BYTE ANI 7FH ; MASK OFF MSB -- IN CASE A WS FILE STAX D ; PUT BYTE INX H ; PT TO NEXT INX D DJNZ MOVE RET * * READ RECORD FROM DISK; NEXT$ADR CONTAINS ADDRESS TO READ TO * ON RETURN, BDOS ERROR CODE IS IN A (0=NO ERROR) * READ$RECORD: MVI C,20 ; READ NEXT RECORD LXI D,FCB ; PT TO FCB CALL BDOS PUSH PSW ; SAVE RETURN CODE LHLD NEXT$ADR ; PT TO LOAD ADDRESS LDA TPA$END ; CHECK AGAINST END PAGE OF TPA CMP H ; IF AT SAME PAGE, YES JZ READ$ERROR LXI D,BUFF ; PT TO BUFFER TO LOAD FROM MVI B,128 ; NUMBER OF BYTES TO MOVE XCHG CALL MOVE XCHG MVI M,CTRLZ ; STORE ENDING CTRLZ IN CASE OF EOF POP PSW ; GET RETURN CODE ORA A ; DONE? <>0 IF SO * READ DONE -- SAVE PTR TO NEXT BLOCK SHLD NEXT$ADR ; SET NEXT ADDRESS RET READ$ERROR: LXI D,READERR CALL PRINT$MESSAGE JMP HELP$EXIT * * PRINT ONE LINE OF INFO SECTION; HL PTS TO LINE UPON ENTRY; * HL PTS TO FIRST CHAR OF NEXT LINE UPON EXIT * PRINT$LINE: MOV A,M ; GET CHAR ANI 7FH ; MASK OUT MSB CPI CR ; EOL? JRZ CRLF CPI LF ; LINE FEED? (WS FILE) JRZ CRLF0 CPI CTRLZ ; END OF FILE? JRZ CRLFC ; DONE IF SO CALL CHAR$OUT ; PRINT CHAR INX H ; PT TO NEXT JR PRINT$LINE * * PRINT CRLF, PT TO FIRST CHAR OF NEXT LINE, AND PAGE IF NECESSARY * CRLF: INX H ; PT TO LF CRLF0: INX H ; PT TO 1ST CHAR OF NEXT LINE CRLFC: CALL CRLF1 ; PRINT CRLF LDA LINE$CNT ; GET LINE COUNT DCR A STA LINE$CNT RNZ ; OK -- CONTINUE MOV A,M ; SET MSB OF FIRST CHAR OF NEXT LINE ORI 80H MOV M,A ; MSB IS SET FOR LATER BACKUP FRAME$PAUSE: CALL PR$LEVEL ; PRINT LEVEL NUMBER LDA FRAME$NUMBER ; INCREMENT FRAME NUMBER INR A STA FRAME$NUMBER LXI D,PAGEMS CALL PRINT$MESSAGE ; PRINT PAGE MESSAGE LXI D,PAGE1MS ; NOT LEVEL 0? LDA HELP$LEVEL ; GET LEVEL NUMBER ORA A ; SET FLAGS JRZ FP1 CALL PRINT$MESSAGE FP1: LXI D,PAGE2MS CALL PRINT$MESSAGE CALL CHAR$IN ; GET RESPONSE CPI MENU$CHAR ; ABORT? JZ HELP ; START OVER IF SO CPI CPM$ABORT$CHAR ; ABORT TO OS JZ HELP$EXIT CPI PRINT$CHAR ; PRINT INFO SECTION? JZ LIST1$INFO CPI ROOT$CHAR ; GO TO ROOT JZ GO$ROOT CPI LEVEL$RET$CHAR ; RETURN TO HIGHER LEVEL JZ LEVEL$RETURN CPI BACKUP$CHAR ; BACK UP? JZ FRAME$BACKUP CPI START$CHAR ; JUMP TO START OF INFO JZ INFO$START FRAME$RESUME: SHLD START$OF$FRAME CALL SET$LINE$CNT CALL CRLF1 ; NEW LINE RET * JUMP TO START OF INFORMATION INFO$START: LHLD START$OF$INFO ; PT TO START OF INFO MVI A,1 ; RESET FRAME COUNT STA FRAME$NUMBER JMP FRAME$RESUME ; CONTINUE PROCESSING * BACK UP TO PREVIOUS FRAME FRAME$BACKUP: CALL BOI$CHECK ; AT BEGINNING OF INFORMATION? JRNZ FB1 ; CONTINUE IF NOT JMP FRAME$PAUSE FB1: DCX H ; BACK UP UNTIL BYTE WITH MSB SET IS FOUND MOV A,M ; GET BYTE ANI 80H JRZ FB1 LDA FRAME$NUMBER ; DECREMENT FRAME NUMBER DCR A ; BACK UP TO CURRENT FRAME NUMBER DCR A ; BACK UP TO PREVIOUS FRAME NUMBER STA FRAME$NUMBER JMP FRAME$RESUME ; CONTINUE PROCESSING * * PRINT CR AND LF ONLY * CRLF1: MVI A,CR ; PRINT CR CALL CHAR$OUT MVI A,LF ; PRINT LF JMP CHAR$OUT * * SET LINE$CNT VARIABLE TO SCREEN SIZE * SET$LINE$CNT: MVI A,LINES$PER$SCREEN-1 STA LINE$CNT RET * * PRINT THE HEADER SECTION AND LOAD FIRST$ENTRY PTR * ON RETURN, C=NUMBER OF POSSIBLE SELECTIONS * PRINT$HEADER: MVI A,0 ; SET NO FRAME STA FRAME$NUMBER LXI H,HELP$BUF CALL SET$LINE$CNT LDA LINE$CNT DCR A STA LINE$CNT MVI A,'A' ; INIT SELECTION CHAR STA SEL$CHAR LXI D,SELECTMS CALL PRINT$MESSAGE MVI C,0 ; COUNT NUMBER OF SELECTIONS * PRINT LINE UNTIL FIRST INFORMATION SECTION FOUND PH1: MOV A,M ; GET CHAR ANI 7FH ; MASK OUT MSB CPI SECT$CHAR JRZ PH2 CPI CTRLZ ; EOF? -- ABORT JZ HELP$EXIT INR C ; INCREMENT SELECTION COUNT LDA SEL$CHAR ; DISPLAY SELECTION CHAR CALL CHAR$OUT INR A ; INCR CHAR STA SEL$CHAR MVI A,'.' CALL CHAR$OUT MVI A,' ' CALL CHAR$OUT CALL PRINT$LINE ; PRINT HEADER LINE JR PH1 * SAVE PTR TO FIRST ENTRY PH2: SHLD FIRST$ENTRY LDA LINE$CNT ; GET COUNT OF REMAINING LINES MOV B,A ; ... IN B ORA A ; ANY LEFT? RZ PH3: CALL CRLF1 ; NEW LINE DJNZ PH3 RET * * PRINT AN INFORMATION SECTION * INFORMATION SECTION IS PTED TO BY HL * PRINT$INFO: SHLD START$OF$INFO ; SET START OF INFORMATION POINTER CALL LOAD$NODE ; LOAD NEW NODE IF DUAL SECT$CHAR SHLD START$OF$FRAME ; SET FRAME POINTER MOV A,M ; SET MSB ORI 80H MOV M,A CALL SET$LINE$CNT MVI A,1 ; A=1 STA FRAME$NUMBER ; SET FRAME NUMBER PI1: CALL PRINT$LINE ; PRINT LINE FROM INFO FILE MOV A,M ; DONE? ANI 7FH ; MASK OUT MSB CPI CTRLZ ; EOF? JRZ PI2 CPI SECT$CHAR ; NEXT SECTION JRZ PI2 CPI FF ; FORM FEED? JRNZ PI1 INX H ; PT TO CHAR AFTER FORM FEED CALL FORM$FEED ; FEED SCREEN JR PI1 * FORM FEED SCREEN FORM$FEED: LDA LINE$CNT ; GET LINE COUNT MOV B,A ; ... IN B FEED$LOOP: PUSH B ; SAVE B CALL CRLFC ; NEW LINE POP B ; GET B DJNZ FEED$LOOP RET * END OF INFO PI2: MOV A,M ; SET MSB OF NEXT BYTE ORI 80H MOV M,A PI2A: CALL CRLF1 ; NEW LINE LDA LINE$CNT ; COUNT DOWN DCR A STA LINE$CNT JRNZ PI2A PI2$MSG: CALL PR$LEVEL ; PRINT LEVEL NUMBER LDA FRAME$NUMBER ; INCREMENT FRAME NUMBER INR A STA FRAME$NUMBER LXI D,ENDMS ; PRINT END OF INFORMATION MSG CALL PRINT$MESSAGE LXI D,PAGE1MS ; PRINT LEVEL UP MESSAGE OPTIONALLY LDA HELP$LEVEL ; GET CURRENT HELP LEVEL ORA A ; SET FLAGS JRZ PI2$MSG1 CALL PRINT$MESSAGE PI2$MSG1: LXI D,PAGE2MS ; PRINT REST OF INFO MESSAGE CALL PRINT$MESSAGE CALL CHAR$IN ; GET ANY CHAR CPI MENU$CHAR ; MENU ABORT JZ HELP CPI CPM$ABORT$CHAR ; ABORT TO OS JZ HELP$EXIT CPI PRINT$CHAR ; PRINT INFORMATION SECTION? JZ LIST1$INFO CPI ROOT$CHAR ; GO TO ROOT JZ GO$ROOT CPI LEVEL$RET$CHAR ; RETURN TO HIGHER LEVEL JZ LEVEL$RETURN CPI BACKUP$CHAR ; BACK UP FROM EOI? JZ PI2$BACKUP CPI START$CHAR ; START OF INFO? JZ PI2$START JMP SET$LINE$CNT ; RESET LINE COUNT IN CASE OF ALL * JUMP TO START OF INFO PI2$START: LHLD START$OF$INFO ; PT TO START OF INFO CALL FRAME$RESUME ; RESET POINTERS MVI A,1 ; RESET FRAME COUNT STA FRAME$NUMBER JMP PI1 ; CONTINUE PROCESSING * BACK UP TO PREVIOUS FRAME PI2$BACKUP: CALL BOI$CHECK ; AT BEGINNING OF INFORMATION? JZ PI2$MSG PI2$BACK: CALL FB1 ; BACK UP TO PREVIOUS FRAME JMP PI1 ; CONTINUE PROCESSING * * CHECK FOR POSITION AT BEGINNING OF INFORMATION SECTION * IF SO, PRINT BACKUP ERROR MESSAGE AND RETURN W/ZERO SET * BOI$CHECK: LHLD START$OF$INFO ; START ADDRESS XCHG ; ... IN DE LHLD START$OF$FRAME ; FRAME ADDRESS MOV A,D ; EQUAL? CMP H RNZ MOV A,E CMP L RNZ LXI D,BACKERR ; BACKUP ERROR CALL PRINT$MESSAGE XRA A ; ZERO FLAG SET STA FRAME$NUMBER ; SET FRAME NUMBER RET ************************************************************** * THIS BODY OF CODE LISTS INFORMATION FROM HELP2 TO THE * PRINTER ************************************************************** * * LIST ONE LINE OF INFO SECTION; HL PTS TO LINE UPON ENTRY; * HL PTS TO FIRST CHAR OF NEXT LINE UPON EXIT * LIST$LINE: MOV A,M ; GET CHAR ANI 7FH ; MASK OUT MSB CPI CR ; EOL? JRZ LCRLF CPI LF ; LINE FEED? (WS FILE) JRZ LCRLF0 CPI CTRLZ ; END OF FILE? JRZ LCRLFC ; DONE IF SO CALL LST$OUT ; PRINT CHAR RZ ; ABORT INX H ; PT TO NEXT JR LIST$LINE * * LIST CRLF, PT TO FIRST CHAR OF NEXT LINE, AND PAGE IF NECESSARY * LCRLF: INX H ; PT TO LF LCRLF0: INX H ; PT TO 1ST CHAR OF NEXT LINE LCRLFC: CALL LCRLF1 ; PRINT CRLF LDA LINE$CNT ; GET LINE COUNT DCR A STA LINE$CNT JRNZ LNOABT ; OK -- CONTINUE LCRLF1: MVI A,CR ; SEND TO PRINTER CALL LST$OUT RZ ; ABORT MVI A,LF ; FALL THRU TO LST$OUT * PRINT CHARACTER IN A ON PRINTER; AFFECT NO REGISTERS LST$OUT: PUSH H ; SAVE REGS PUSH D PUSH B MOV E,A ; CHAR IN E MVI C,5 ; BDOS PRINTER OUTPUT ROUTINE CALL BDOS MVI E,0FFH ; CONDITIONAL INPUT MVI C,6 ; DIRECT CONSOLE I/O CALL BDOS POP B ; RESTORE REGS POP D POP H CPI CTRLC ; ABORT? RET LNOABT: MVI A,0FFH ; SET NO ABORT RETURN ORA A ; SET FLAGS RET * * LIST THE CURRENT INFORMATION SECTION * INFORMATION SECTION IS PTED TO BY START$OF$INFO * LIST1$INFO: LXI D,PRINT$WAIT$MSG CALL PRINT$MESSAGE LHLD START$OF$INFO ; PREPARE TO LIST ENTIRE INFO SECTION XRA A ; CLEAR FRAME LIST FLAG STA LFR$FLAG CALL CHAR$IN ; GET USER INPUT CPI 'S' ; SCREEN DISPLAY ONLY JRNZ LIST2$INFO LHLD START$OF$FRAME ; LIST CURRENT FRAME ONLY MVI A,0FFH ; SET FLAG STA LFR$FLAG ; LIST FRAME ONLY LIST2$INFO: CPI CTRLC ; CHECK FOR ^C TO ABORT CNZ LIST$INFO ; DO PRINTOUT LHLD START$OF$FRAME ; RETURN TO FRAME WE WERE ON CALL FRAME$RESUME LDA FRAME$NUMBER ; ADJUST FRAME NUMBERING DCR A STA FRAME$NUMBER JMP PI1 ; RESUME AT PI1 * LIST$INFO: LXI D,PRINT$LMSG ; PRINT ABORT OPTION MESSAGE CALL PRINT$MESSAGE CALL SET$LINE$CNT LI1: CALL LIST$LINE ; LIST LINE FROM INFO FILE CPI CTRLC ; ABORT? RZ MOV A,M ; DONE? ANI 7FH ; MASK OUT MSB CPI CTRLZ ; EOF? RZ ; RESUME IF AT END OF INFO CPI SECT$CHAR ; NEXT SECTION RZ ; RESUME IF AT END OF INFO CPI FF ; FORM FEED? JRNZ LI1 INX H ; PT TO CHAR AFTER FORM FEED CALL LFORM$FEED ; FEED PRINTER LDA LFR$FLAG ; LIST FRAME ONLY? ORA A ; 0=NO RNZ JR LI1 * FORM FEED SCREEN LFORM$FEED: CALL LCRLFC ; NEW LINE RET ************************************************************** * END OF BODY OF CODE WHICH LISTS INFORMATION FROM HELP2 TO * THE PRINTER ************************************************************** * * AT THE BEGINNING OF AN INFORMATION SECTION (HL PTS TO FIRST CHAR) * CHECK TO SEE IF ANOTHER SECT$CHAR FOLLOWS, AND, IF SO, LOAD THE * SPECIFIED FILE AS A NEW NODE AND BEGIN PROCESSING IT * LOAD$NODE: INX H ; PT TO POSSIBLE 2ND SECT$CHAR MOV A,M ; GET IT DCX H ; PREP FOR RETURN ANI 7FH ; MASK MSB CPI SECT$CHAR ; ANOTHER ONE? RNZ ; PROCESS NORMALLY IF NOT * WE HAVE A NEW NODE -- CHECK TO SEE IF WE CAN NEST AGAIN LDA HELP$LEVEL ; GET CURRENT HELP LEVEL CPI HELP$MAX ; AT MAXIMUM? JRNZ LOAD$NODE1 LXI D,LEVELERR ; LEVEL ERROR MESSAGE CALL PRINT$MESSAGE JMP HELP$EXIT * WE HAVE NOT REACHED LEVEL LIMIT, SO CONTINUE * AT THIS TIME, A=HELP LEVEL INDEX AND HL = PTR TO CURRENT SECTION (::) LOAD$NODE1: * SAVE CURRENT HELP FILE NAME FOR RETURN INX H ; PT TO SECTION SECT$CHAR INX H ; NOW POINTING TO FILE NAME PUSH H ; SAVE PTR CALL COMP$HELP$NAME$PTR ; HL=POINTER TO STACK ELT INDEXED BY A XCHG ; DE=ADDRESS OF NEXT ELEMENT * COPY CURRENT NODE ELEMENT NAME INTO NEXT STACK ELEMENT LXI H,FCB+1 ; PT TO FILE NAME MVI B,11 ; 11 BYTES CALL MOVE * INCREMENT HELP LEVEL LDA HELP$LEVEL ; GET OLD LEVEL INR A ; SET NEW LEVEL STA HELP$LEVEL * SET UP FCB FOR NEW FILE LXI D,LOADING$MSG CALL PRINT$MESSAGE POP H ; GET PTR TO NEW FILE NAME LXI D,FCB+1 ; PT TO FCB NAME MVI B,8 ; 8 CHARS MAX CALL LOAD$FCB ; PLACE INTO FCB WITH ERROR CHECKING MVI A,'.' ; DECIMAL BETWEEN FILE NAME AND TYPE CALL CHAR$OUT MVI B,3 ; 3 CHARS MAX FOR TYPE CALL LOAD$FCB ; PLACE INTO FCB WITH ERROR CHECKING CALL CRLF1 ; NEW LINE JMP START1 ; LOAD NEW HELP FILE * * LOAD FCB PTED TO BY DE WITH "NORMAL" FILE NAME PTED TO BY HL FOR B BYTES * LOAD$FCB: MOV A,M ; GET CHAR INX H ; PT TO NEXT CPI '.' ; DONE IF DECIMAL JRZ LOAD$FCB$FILL CPI ' '+1 ; DONE IF < JRC LOAD$FCB$FILL CALL CAPS ; CAPITALIZE CALL CHAR$OUT ; PRINT FILE NAME AND TYPE STAX D ; STORE CHAR INX D ; PT TO NEXT DJNZ LOAD$FCB MOV A,M ; CHECK FOR ERROR ANI 7FH ; MASK MSB INX H ; PT TO NEXT CHAR CPI '.' ; OK IF '.' RZ CPI ' '+1 ; OK IF RC LXI D,LOADERR CALL PRINT$MESSAGE JMP HELP$EXIT LOAD$FCB$FILL: MOV C,A ; SAVE CHAR THAT TERMINATED STRING LOAD$FCB$LOOP: MVI A,' ' ; FILL REST OF FCB STAX D ; STORE INX D ; PT TO NEXT DJNZ LOAD$FCB$LOOP MOV A,C ; GET CHAR THAT TERMINATED STRING RET * * GO TO ROOT * GO$ROOT: LDA HELP$LEVEL ; AT ROOT? ORA A ; 0=YES JZ HELP ; RETURN TO HELP MVI A,0 ; SET ROOT INDEX JR GORET * * RETURN TO PREVIOUS HELP LEVEL * LEVEL$RETURN: LDA HELP$LEVEL ; ARE WE AT THE LOWEST LEVEL? ORA A ; 0=YES JRNZ LRET LXI D,LRETERR CALL PRINT$MESSAGE JMP HELP * SET NEW HELP LEVEL LRET: DCR A ; DOWN 1 * GO TO HELP LEVEL INDEXED IN A GORET: STA HELP$LEVEL ; SET NEW HELP LEVEL CALL COMP$HELP$NAME$PTR ; HL=POINTER TO TARGET HELP FILE NAME PUSH H ; SAVE PTR TO FILE NAME LXI D,LOADING$MSG ; PRINT NAME OF FILE TO BE LOADED CALL PRINT$MESSAGE MVI B,8 ; 8 CHARS TO FILE NAME GORET$NAME: MOV A,M ; GET CHAR CPI ' ' ; END OF NAME? INX H ; PT TO NEXT JRZ GORET$NAME0 CALL CHAR$OUT ; PRINT FILE NAME DJNZ GORET$NAME JMP GORET$NAME1 GORET$NAME0: DCR B ; COUNT DOWN JRZ GORET$NAME1 INX H ; SKIP NEXT SPACE JR GORET$NAME0 GORET$NAME1: MVI A,'.' ; PRINT DECIMAL CALL CHAR$OUT MVI B,3 ; PRINT FILE TYPE GORET$NAME2: MOV A,M ; GET CHAR INX H ; PT TO NEXT CALL CHAR$OUT ; PRINT IT DJNZ GORET$NAME2 CALL CRLF1 ; NEW LINE POP H ; GET PTR TO FILE NAME LXI D,FCB+1 ; COPY ELEMENT INTO FCB MVI B,11 ; 11 BYTES CALL MOVE JMP START1 ; LOAD ENTRY * * COMPUTE POINTER TO HELP NAME ENTRY INDEXED BY HELP LEVEL IN A * COMP$HELP$NAME$PTR: CALL COMP$OFFSET ; COMPUTE OFFSET IN TABLE LXI D,HELP$NAME$STACK ; PT TO BASE OF HELP NAMES DAD D ; ADD IN OFFSET RET * * COMPUTE OFFSET INTO TABLE BASED ON INDEX A * OFFSET = A * 11 * COMP$OFFSET: MOV L,A ; VALUE IN HL MVI H,0 MOV E,L ; DE=HL MOV D,H DAD H ; *2 DAD H ; *4 DAD H ; *8 DAD D ; *9 DAD D ; *10 DAD D ; *11 RET * * PRINT LEVEL NUMBER * PR$LEVEL: LDA HELP$LEVEL ; DON'T PRINT LEVEL 0 ORA A ; 0? JRZ PR$FRAME LXI D,LEVEL$MESSAGE ; PRINT HEADER CALL PRINT$MESSAGE LDA HELP$LEVEL ; GET NUMBER CALL PR$DEC ; PRINT AS DECIMAL LXI D,LEVEL2$MESSAGE ; PRINT END HEADER CALL PRINT$MESSAGE PR$FRAME: LDA FRAME$NUMBER ; GET CURRENT FRAME NUMBER ORA A ; SET FLAGS RZ ; NO FRAME? CALL PR$DEC ; PRINT AS DECIMAL LXI D,LEVEL3$MESSAGE CALL PRINT$MESSAGE RET * PRINT A AS DECIMAL PR$DEC: PUSH PSW ; SAVE VALUE XRA A STA LD$SPACE POP PSW ; GET VALUE MVI B,100 ; PRINT 100'S CALL PDEC MVI B,10 ; PRINT 10'S CALL PDEC ADI '0' ; PRINT 1'S JMP CHAR$OUT PDEC: MVI C,0 ; SET VALUE PDEC1: SUB B ; SUBTRACT POWER JRC PDEC2 INR C ; INCREMENT VALUE JR PDEC1 PDEC2: ADD B ; ADD POWER BACK IN MOV B,A ; SAVE A IN B LDA LD$SPACE ; GET LEADING FLAG ORA A ; NON-ZERO=PRINT JRNZ PDEC3 MOV A,C ; GET DIGIT STA LD$SPACE ; NEW FLAG ORA A ; ZERO? JRNZ PDEC3 ; PRINT BYTE IN C MVI A,' ' ; PRINT LEADING SPACE JR PDEC4 PDEC3: MOV A,C ; GET VALUE ADI '0' ; CONVERT TO ASCII PDEC4: CALL CHAR$OUT ; PRINT CHAR MOV A,B ; RESTORE A RET ********************************************************* * MESSAGE AND BUFFER SECTION * ********************************************************* HELPMS: DB 'HELP for ZCPR2, Version ' DB (VERS/10)+'0','.',(VERS MOD 10)+'0',CR,LF,'$' HELP$DEF$MSG: DB CR,LF,'Default HELP Facility Invoked' DB CR,LF,' Available HELP Files are --',CR,LF,'$' HELP$EDEF$MSG: DB CR,LF,' Type Any Character for Default Info (^C to Abort) - $' SELECTMS: DB CR,LF,' HELP File Selections are --',CR,LF,'$' ENDMS: DB 'EOI ' PAGEMS: DB '^C=Exit $' ; ABORT TO CP/M CHAR PAGE1MS: DB LEVEL$RET$CHAR,'=Level ' ; RETURN TO HIGHER NODE DB ROOT$CHAR,'=Root $' ; RETURN TO ROOT PAGE2MS: DB MENU$CHAR,'=Menu ' ; ABORT TO MENU CHAR DB START$CHAR,'=Start ' ; JUMP TO START OF INFORMATION CHAR DB BACKUP$CHAR,'=Last ' ; BACK UP TO PREVIOUS FRAME CHAR DB PRINT$CHAR,'=Print ' ; PRINT CURRENT INFO SECTION ; DB 'CR=Next ' DB '$' PRINT$LMSG: DB 'Printing in Progress -- Strike ^C to Abort $' PRINT$WAIT$MSG: DB 'Please Set Top-of-Form on Printer' DB CR,LF,' Strike S to Print this Screen Only, ^C to Abort, or' DB CR,LF,'Any Other Char to Print Entire Information Section - $' WILD$ERR: DB CR,LF,'HELP FATAL ERROR -- File Name Contains Wild Card$' ERR1: DB CR,LF,'HELP FATAL ERROR -- File not Found$' ERR2: DB CR,LF,'HELP ERROR -- Invalid Response',CR,LF,'$' ERR3: DB CR,LF,'HELP ERROR -- EOF on HELP File',CR,LF,'$' BACKERR: DB CR,LF,'HELP ERROR -- Not Possible to Backup Before Start of ' DB 'Info',CR,LF,'$' LEVELERR: DB CR,LF,'HELP ERROR -- Node Level Limit Reached -- Aborting' DB CR,LF,'$' LOADERR: DB CR,LF,'HELP ERROR -- Invalid File Name in Load',CR,LF,'$' LRETERR: DB CR,LF,'HELP ERROR -- No Higher Level to Return to',CR,LF,'$' READERR: DB CR,LF,'HELP ERROR -- Not Enough Room for HELP File',CR,LF,'$' LEVEL$MESSAGE: DB 'Level $' LEVEL2$MESSAGE: DB '/ $' LEVEL3$MESSAGE: DB ': $' PROMPT1$MESSAGE: DB 'Type ^C=Exit$' PROMPT2$MESSAGE: DB ' ',LEVEL$RET$CHAR,'=Level ' DB ROOT$CHAR,'=Root$' PROMPT3$MESSAGE: DB ' or Enter Selection $' LOADING$MSG: DB CR,LF,'Loading HELP File $' LFR$FLAG: DS 1 ; LIST FRAME ONLY FLAG (FOR PRINT FUNCTION) CUR$USER: DS 1 ; NUMBER OF CURRENT USER TPA$END: DS 1 ; END PAGE ADDRESS OF TPA START$OF$INFO: DS 2 ; PTR TO START OF CURRENT INFORMATION BLOCK START$OF$FRAME: DS 2 ; PTR TO START OF CURRENT FRAME SEL$CHAR: DS 1 ; SELECTION TABLE OPTION CHAR FIRST$ENTRY: DS 2 ; PTR TO FIRST ENTRY OF INFORMATION SECTION LINE$CNT: DS 1 ; LINE COUNT BUFFER NAME$COUNT: DS 1 ; COUNT OF FILE NAMES/LINE DFFLG: DS 1 ; DEFAULT FILE FLAG (0=NOT SEARCH FOR, 1=YES) NEXT$ADR: DS 2 ; NEXT LOAD ADDRESS LD$SPACE: DS 1 ; LEADING SPACE FLAG FOR DECIMAL PRINT HELP$LEVEL: DS 1 ; NUMBER OF HELP LEVEL CURRENT NODE IS AT (0=BOTTOM) FRAME$NUMBER: DS 1 ; NUMBER OF CURRENT FRAME HELP$NAME$STACK: DS 11*HELP$MAX ; STACK OF HELP FILE NAMES OF EACH LEVEL DS 80 ; STACK SPACE STACK: DS 2 ; CP/M STACK PTR * * Help Files are Loaded Here * HELP$BUF equ $ END