home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPMHELP
/
HELP18U.AQM
/
HELP18U.ASM
Wrap
Assembly Source File
|
2000-06-30
|
37KB
|
1,534 lines
* PROGRAM NAME: HELP
* AUTHOR: RICHARD CONN Update for USQ by Dave Rand
* DATE: 12 OCT 83
* VERSION: 1.8
* PREVIOUS VERSIONS: 1.6 (9 SEP 81), 1.7 (10 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)
VERS EQU 18 ; VERSION NUMBER
*****************************************************************
* *
* HELP -- DISPLAY HELP FILE INFORMATION TO USER ON CON: *
* *
* -- Command Format -- *
* THE HELP COMMAND IS OF THE GENERAL FORM: *
* HELP <FILENAME>.<TYP> *
* *
* <FILENAME>.<TYP> IS OPTIONAL; IF OMITTED COMPLETELY, *
* 'HELP.HLP' IS ASSUMED; IF JUST <TYP> IS OMITTED, FILE TYPE *
* IS ASSUMED TO BE '.HLP' *
* *
* -- Basic Background Information -- *
* THE HELP COMMAND DISPLAYS THE INFORMATION IN A HELP *
* FILE TO THE USER. THERE ARE TWO BASIC TYPES OF HELP FILES -- *
* (1) INDEXED AND (2) NON-INDEXED. INDEXED HELP FILES ARE *
* THOSE WHICH CONTAIN SEVERAL SECTIONS; THE INDIVIDUAL MAY *
* READ ALL OF SUCH A HELP FILE OR JUST SELECTED SECTIONS OF *
* THIS FILE. NON-INDEXED HELP FILES CONTAIN ONLY ONE SECTION. *
* STRUCTURALLY SPEAKING, HELP FILES CONSIST OF TWO PARTS: *
* THE HEADER PART AND THE INFORMATION PART. THE INFORMATION *
* PART OF A HELP FILE BEGINS WITH A LINE WHOSE FIRST CHARACTER *
* IS A COLON. THE TITLE OF THE INFORMATION SECTION IS ON THIS *
* LINE. THE INFORMATION SECTION CONTINUES UNTIL THE NEXT *
* INFORMATION SECTION (LINE STARTING WITH A COLON) OR THE END *
* OF THE FILE IS ENCOUNTERED. THE HEADER PART CONSISTS OF A *
* GROUP OF LINES BEFORE THE FIRST INFORMATION SECTION. IF THE *
* FIRST LINE OF A HELP FILE STARTS WITH A COLON, THEN THERE IS *
* NO HEADER PART, AND THE HELP FILE IS DUMPED AS ONE *
* INFORMATION SECTION. *
* THE INFORMATION SECTION IS ITSELF DIVIDED INTO PARTS, *
* CALLED FRAMES. A FRAME IS ONE SCREEN DISPLAY, THE SIZE OF *
* WHICH IS SET BY AN EQUATE. IF THE HELP FILE CONTAINS A FORM *
* FEED CHARACTER, THEN THE CURRENT FRAME IS ABRUPTLY TERMINATED *
* AND THE RESET OF THE SCREEN DISPLAY IS FILLED WITH BLANK *
* LINES. OTHERWISE, WHEN THE INDICATED NUMBER OF LINES HAVE *
* BEEN DISPLAYED, THE HELP PROGRAM PAUSES TO ALLOW THE USER TO *
* VIEW THE INFORMATION AND SELECT THE NEXT DIRECTION IN WHICH *
* TO GO. *
* *
* -- Traversing the HELP File -- *
* WHILE IN THE HELP SYSTEM, THE USER IS GIVEN SEVERAL *
* OPTIONS AT ALL TIMES AS TO WHAT HE CAN DO. *
* AT THE MENU LEVEL OF INDEXED HELP FILES, THE USER CAN *
* MOVE IN THE FOLLOWING DIRECTIONS: *
* 1. SELECTION OF A MENU ITEM, IN WHICH CASE *
* HE ENTERS THAT INFORMATION SECTION *
* 2. MOVE UP TO THE PREVIOUS LEVEL. IF THE HELP *
* FILE THE USER IS IN WAS REACHED THROUGH ANOTHER HELP FILE, *
* THE USER CAN RETURN TO THAT HELP FILE (MOVE UP A LEVEL). *
* IF THE USER WAS IN THE "SELECT ALL ITEMS" MODE, HE CONTINUES *
* WITH THE PREVIOUS HELP FILE WHERE HE LEFT OFF; IF THE USER *
* WAS LOOKING AT A SPECIFIC MENU ITEM (WHICH CALLED THE HELP *
* FILE HE IS IN NOW), HE IS RETURNED TO THE MENU OF THE CALLING *
* HELP FILE. *
* 3. EXIT TO CP/M. AT ALL TIMES, THE USER IS *
* ALLOWED TO RETURN TO CP/M. *
* WHILE IN AN INFORMATION SECTION, THE USER MAY *
* MOVE IN THE FOLLOWING DIRECTIONS: *
* 1. FORWARD TO THE NEXT FRAME. IF AT THE END *
* OF THE INFORMATION SECTION, THIS RETURNS THE USER TO THE *
* MENU IF IT IS AN INDEXED HELP FILE, TO CP/M IF THE USER IS *
* IN A NON-INDEXED HELP FILE AT LEVEL 0 (NOT CALLED BY ANOTHER *
* HELP FILE), OR TO THE CALLING HELP FILE IF NOT AT LEVEL 0. *
* 2. BACKWARD TO THE PREVIOUS FRAME. IF AT THE *
* BEGINNING OF AN INFORMATION SECTION, AN ERROR MESSAGE IS *
* PRINTED. *
* 3. TO THE MENU IF IN AN INDEXED HELP FILE. *
* 4. TO THE START OF THE CURRENT INFORMATION *
* SECTION DIRECTLY. *
* 5. TO THE PREVIOUS LEVEL (CALLING HELP FILE). *
* *
* -- Nodes and Help File Nesting -- *
* AN INFORMATION SECTION MAY BEGIN WITH A DOUBLE COLON *
* (::), AND THIS DESIGNATOR IS FOLLOWING BY THE FILE NAME OF A *
* HELP FILE WHICH IS TO BE LOADED AS A NODE. NODES TO THE HELP *
* PROGRAM ARE COMPLETE HELP FILES IN THEMSELVES, AND THEY MAY *
* REFER TO OTHER NODES AS WELL. IN THIS WAY, A TREE STRUCTURE *
* MAY BE DESIGNED BY THE AUTHOR OF A HELP FILE, EACH NODE OF *
* THE TREE BEING A HELP FILE IN ITS OWN RIGHT (WHICH MAY BE *
* ACCESSED INDEPENDENTLY). NODES MAY BE NESTED A NUMBER OF *
* LEVELS, SPECIFIED BY THE HELP$MAX EQUATE. *
* TO VIEW THIS CONCEPT MORE CLEARLY, THE FOLLOWING DIAGRAM*
* IS OFFERED: *
* -- Basic HELP File -- *
* :Info Sect 1 :Info Sect 2 :Info Sect 3 :Info Sect 4 : *
* : Text : HELP File : Text : HELP File : *
* / \ / \ *
* -- SubHelp File 1 -- -- SubHelp File 2 --*
* :Info Sect 1 :Info Sect 2 : :Info Sect 1 :Info Sect2*
* : Text : HELP File : : Text : Text *
* / \ *
* -- SubSubHelp File 1 -- *
* :Info Sect 1 :Info Sect 2 :Info Sect 3 : *
* : Text : HELP File : HELP File : *
* / \ / \ *
* -- Sub3Help File 1 -- -- Sub3Help File 2 -- *
* :Info Sect : :Info Sect 1 :Info Sect 2: *
* : Text : : Text : HELP File : *
* / \ *
* -- Sub4Help File -- *
* :Info Sect 1 :Info Sect 2: *
* : Text : Text : *
* *
* AS THE USER CAN SEE, TREE STRUCTURES ARE NOW POSSIBLE. *
* ONE HELP FILE CAN REFERENCE ANOTHER WHICH INTURN REFERENCES *
* ANOTHER AND SO ON. THERE IS A LIMIT TO HOW DEEP THE NESTING *
* MAY GO, AND THAT IS SPECIFIED IN THE EQUATE FOR HELP$MAX. *
* *
* -- What Help Can Do -- *
* SINCE A HELP FILE MUST BE MEMORY RESIDENT, THIS IS *
* CONVENIENT IN TWO WAYS: (1) "MASTER" HELP FILES MAY BE *
* CREATED WHICH REFERENCE OTHER HELP FILES, AND THE INFORMATION *
* ACCESSED FROM A MASTER HELP FILE MAY ENCOMPASS ALL OF THE *
* USER'S HELP FILE AND (2) IF THE USER NEEDS INFORMATION *
* IN A SPECIFIC SUBJECT AREA AND KNOWS WHICH HELP FILE REFERS *
* TO THE INFORMATION HE NEEDS, HE NEED NOT LOAD THE MASTER *
* AND THEN TRAVERSE THE TREE TO THE INFORMATION HE NEEDS; HE *
* MAY SPECIFY THE SPECIFIC HELP FILE DIRECTLY. *
* *
* -- Command-Search Hierarchy -- *
* ONE OTHER POINT TO NOTE IS THAT THE HELP PROGRAM NOW *
* EMPLOYS A COMMAND-SEARCH HIERARCHY IN LOCATING A REFERENCED *
* HELP FILE. ONCE A FILE SPECIFICATION IS GIVEN, THE HELP *
* PROGRAM SEARCHES THE CURRENT USER AREA ON THE CURRENT DISK FOR*
* THE FILE; IF NOT FOUND, IT DROPS TO USER AREA 0 (MAY BE *
* CHANGED) ON THE CURRENT DISK IF THE USER IS NOT ALREADY THERE *
* AND LOOKS FOR THE FILE; IF NOT FOUND THIS TIME, IT DROPS TO *
* USER AREA 0 OF THE DISK ON DRIVE A: AND SEARCHES FOR THE FILE.*
* IF NOT FOUND AT THIS POINT, HELP CHECKS TO SEE IF THE REFER- *
* ENCED FILE WAS HELP.HLP, IN WHICH CASE IT PRESENTS THE BUILT- *
* IN DOCUMENTATION (SEE END OF PROGRAM); FINALLY, IF NONE OF THE*
* ABOVE ARE TRUE, HELP ABORTS WITH AN ERROR MESSAGE. *
* *
* -- HELP File Structure Warning -- *
* THERE MUST BE THE SAME NUMBER OF LINES IN THE HEADER *
* PART AS THERE ARE INFORMATION SECTIONS. IF NOT, A HELP *
* FILE ERROR WILL BE ISSUED IF THE HELP COMMAND ATTEMPTS TO *
* READ BEYOND THE END OF THE HELP FILE IN ITS SEARCH FOR AN *
* INFORMATION SECTION. *
* *
*****************************************************************
*****************************************************************
* *
* THE HELP PROGRAM IS COMPLETELY TRANSPORTABLE BETWEEN CP/M *
* SYSTEMS. *
* *
*****************************************************************
*****************************************************************
* CP/M AND BASIC CHARACTER DEFINITIONS *
*****************************************************************
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 ; <CR>
LF EQU 0AH ; <LF>
FF EQU 'L'-40H ; CTRL-L = FORM FEED
CTRLZ EQU 'Z'-40H ; CTRL-Z
CTRLC EQU 'C'-40H ; CTRL-C
*****************************************************************
* SPECIAL CONTROL CHARACTERS WHICH MAY BE RESET BY USER *
*****************************************************************
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 ABORT TO CP/M
LEVEL$RET$CHAR EQU '^' ; RETURN TO PREVIOUS HELP LEVEL
ROOT$CHAR EQU '.' ; RETURN TO ROOT OF HELP
*****************************************************************
* USER CUSTOMIZATION -- LINES PER SCREEN DISPLAY *
*****************************************************************
LINES$PER$SCREEN EQU 24 ; ASSUME 24 LINES/SCREEN
*****************************************************************
* USER CUSTOMIZATION -- DEFAULT USER NUMBER *
*****************************************************************
DEFAULT$USER EQU 0 ; DEFAULT USER NUMBER = 0
*****************************************************************
* USER CUSTOMIZATION -- DEFAULT DISK *
*****************************************************************
DEFAULT$DISK EQU 'A' ; DEFAULT DISK = A:
*****************************************************************
* USER CUSTOMIZATION -- NUMBER OF NODES (LEVELS) IN HELP TREE *
*****************************************************************
HELP$MAX EQU 10 ; DEFAULT = 10 (SPACE=11*HELP$MAX)
*****************************************************************
* START OF PROGRAM *
*****************************************************************
ORG 100H
START:
LXI H,0 ; GET SP
DAD SP
SHLD STACK
LXI SP,STACK ; NEW STACK
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?
JZ DEFAULT$FN
ORA A ; ALSO NONE
JNZ START1
* INSERT 'HELP.HLP' INTO FCB
DEFAULT$FN:
DCX H ; PT TO FCB
LXI D,DEFFN
MVI B,12 ; 12 BYTES
XCHG
CALL MOVE ; MOVE (HL) TO (DE) FOR (B) BYTES
MVI A,1 ; TURN ON DEFAULT FILE FLAG
STA DFFLG
JMP START2
* 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
DCR B ; COUNT DOWN
JNZ FCB$FILL
* CHECK FOR FILE TYPE
LXI H,FCB+9 ; CHECK FOR FILE TYPE
MOV A,M
CPI ' ' ; NONE?
JZ DEFAULT$EXT
ORA A ; NONE ALSO
JNZ START2
* PLACE DEFAULT FILE TYPE OF '.HLP' IN FCB
DEFAULT$EXT:
LXI D,DEFTYP
MVI B,3
XCHG
CALL MOVE ; MOVE (HL) TO (DE) FOR (B) BYTES
* OPEN FILE
START2:
MVI A,0FFH ; SET NO CHANGE FLAG
STA CUR$USER ; SET NO USER CHANGE
STA CUR$DISK ; SET NO DISK CHANGE
* OPTION 1: TRY TO OPEN FILE IN CURRENT USER NUMBER ON CURRENT DISK
LXI D,FCB ; PT TO FCB
MVI C,15 ; OPEN FILE
CALL BDOS
CPI 255 ; NOT PRESENT?
JNZ START3
MVI C,12 ; GET VERSION NUMBER
CALL BDOS
MOV A,H ; CP/M 1.X?
ORA L
JZ START2$DISK ; CHECK FOR DEFAULT DISK IF SO
* OPTION 2: TRY TO OPEN FILE IN USER 0 ON CURRENT DISK
MVI E,0FFH ; GET CURRENT USER NUMBER
MVI C,32 ; GET/SET USER CODE
CALL BDOS
CPI DEFAULT$USER ; CHECK IF AT USER 0 (OR DEFAULT USER)
JZ START2$DISK ; DON'T TRY IF AT USER 0
STA CUR$USER ; SAVE FOR LATER
MVI E,DEFAULT$USER ; SET USER 0 (OR DEFAULT USER)
MVI C,32 ; GET/SET USER CODE
CALL BDOS
LXI D,FCB ; TRY TO OPEN FILE AGAIN
MVI C,15 ; OPEN FILE
CALL BDOS
CPI 255 ; NOT PRESENT?
JNZ START3
* OPTION 3: TRY TO OPEN FILE IN USER 0 ON DEFAULT DISK IF NOT CURRENT DISK
START2$DISK:
MVI C,25 ; DETERMINE CURRENT DISK
CALL BDOS
CPI DEFAULT$DISK-'A' ; ON DEFAULT DISK?
JZ START2$DEFAULT
STA CUR$DISK ; SAVE DISK NUMBER IN BYTE
MVI E,DEFAULT$DISK-'A' ; SELECT DISK A:
MVI C,14 ; SELECT DISK
CALL BDOS
LXI D,FCB ; TRY TO OPEN FILE ONE LAST TIME
MVI C,15 ; OPEN FILE
CALL BDOS
CPI 255 ; NOT PRESENT?
JNZ START3
* CHECK FOR DEFAULT FILE SEARCH
START2$DEFAULT:
CALL RESET$SYSTEM ; RESTORE CURRENT DISK AND USER IF CHANGED
* File not found, look for HQP files
lxi h,fcb+1+8+1 ;see if already Q
mov a,m
ani 127
mvi m,'Q'
cpi 'Q'
jnz start2 ;skip back, and try again
LDA DFFLG ; GET DEFAULT FILE FLAG
ORA A ; 1=YES, SEARCH FOR DEFAULT FAILED
JNZ HELP ; DISPLAY DEFAULT HELP FILE INFORMATION
* FILE NOT FOUND -- FATAL ERROR
LXI D,ERR1 ; FILE NOT FOUND
CALL PRINT$MESSAGE
JMP HELP$EXIT
* LOAD HELP FILE INFORMATION
START3:
LXI H,HELP$BUF ; PT TO BUFFER
SHLD NEXT$ADR ; SET PTR
lda fcb+1+8+1 ;see if sq file
ani 127
cpi 'Q'
jnz start4
call usq
jmp start4a
* READ RECORDS UNTIL EOF
START4:
CALL READ$RECORD ; READ INFO
ORA A ; DONE? 0=NO
JZ START4
start4a:
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
JNZ 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
JZ 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:
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
JZ HELP1A
CALL PRINT$MESSAGE
HELP1A:
LXI D,PROMPT3$MESSAGE
CALL PRINT$MESSAGE
POP B ; GET C
CALL CHAR$IN ; GET RESPONSE
CPI CTRLC ; RETURN TO CP/M
JZ 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
JZ BAD$RESPONSE
JNC HELP2
* INVALID RESPONSE
BAD$RESPONSE:
LXI D,ERR2 ; INVALID RESPONSE
CALL PRINT$MESSAGE
JMP 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?
JNC BAD$RESPONSE
LHLD FIRST$ENTRY ; GET PTR TO FIRST ENTRY
* PRINT INFORMATION WHEN COUNT IS ZERO
HELP3:
DCR B ; COUNT DOWN
JNZ HELP4
CALL PRINT$INFO ; PRINT INFO PTED TO BY HL
JMP HELP1
* LOCATE NEXT INFORMATION SECTION
HELP4:
MOV A,M ; <CTRL-Z>?
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)?
JZ HELP5
CPI CR ; <CR>?
JNZ HELP4
INX H ; 1ST BYTE OF NEXT LINE
HELP5:
MOV A,M ; GET CHAR
ANI 7FH ; MASK OUT MSB
CPI SECT$CHAR ; NEW SECTION?
JZ HELP3 ; CONTINUE LOOP IF SO
CPI CTRLZ ; EOF?
JNZ 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 IF CHANGED
*
RESET$SYSTEM:
LDA CUR$DISK ; CHECK DISK
CPI 0FFH ; 0FFH=NO CHANGE
JZ RESET$SYS1
MOV E,A ; DISK IN E
MVI C,14 ; SELECT DISK
CALL BDOS
RESET$SYS1:
LDA CUR$USER ; CHECK USER
CPI 0FFH ; 0FFH=NO CHANGE
RZ
MOV E,A ; USER IN E
MVI C,32 ; GET/SET USER CODE
CALL BDOS
RET
*
* 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
DCR B ; COUNT DOWN
JNZ 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
POP PSW ; GET RETURN CODE
ORA A ; DONE?
JZ READ$DONE ; RETURN IF NOT
* CHECK FOR CTRLZ
PUSH H ; SAVE PTR TO NEXT ADDRESS
LHLD NEXT$ADR ; PT TO BEGINNING OF BLOCK
MVI B,128 ; CHECK 128 BYTES
CTRLZ$CHECK:
MOV A,M ; GET BYTE
ANI 7FH ; MASK OUT MSB
INX H ; PT TO NEXT
CPI CTRLZ ; EOF?
JZ CTRLZ$FOUND
DCR B ; COUNT DOWN
JNZ CTRLZ$CHECK
LXI D,CTRLZERR
CALL PRINT$MESSAGE ; NO CTRLZ ERROR
JMP HELP$EXIT
* FILL REST OF BLOCK WITH CTRLZ
CTRLZ$FOUND:
DCR B ; COUNT DOWN
JZ CTRLZ$DONE
MVI M,CTRLZ ; FILL REST OF BLOCK WITH CTRLZ
INX H ; PT TO NEXT
JMP CTRLZ$FOUND
CTRLZ$DONE:
POP H ; PT TO NEXT BLOCK ADDRESS
* READ OK -- SAVE PTR TO NEXT BLOCK
READ$DONE:
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?
JZ CRLF
CPI LF ; LINE FEED? (WS FILE)
JZ CRLF0
CPI CTRLZ ; END OF FILE?
JZ CRLFC ; DONE IF SO
CALL CHAR$OUT ; PRINT CHAR
INX H ; PT TO NEXT
JMP 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
JZ 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 ; CP/M ABORT
JZ HELP$EXIT
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
JMP FRAME$RESUME ; CONTINUE PROCESSING
* BACK UP TO PREVIOUS FRAME
FRAME$BACKUP:
CALL BOI$CHECK ; AT BEGINNING OF INFORMATION?
JNZ 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
JZ 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
CALL CHAR$OUT
RET
*
* 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
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
JZ 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
JMP PH1
* SAVE PTR TO FIRST ENTRY
PH2:
SHLD FIRST$ENTRY
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?
JZ PI2
CPI SECT$CHAR ; NEXT SECTION
JZ PI2
CPI FF ; FORM FEED?
JNZ PI1
INX H ; PT TO CHAR AFTER FORM FEED
CALL FORM$FEED ; FEED SCREEN
JMP 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
DCR B ; COUNT DOWN
JNZ 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
JNZ 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
JZ 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 ; CP/M ABORT
JZ HELP$EXIT
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
CALL SET$LINE$CNT ; RESET LINE COUNT IN CASE OF ALL
RET
* JUMP TO START OF INFO
PI2$START:
LHLD START$OF$INFO ; PT TO START OF INFO
CALL FRAME$RESUME ; RESET POINTERS
JMP PI1 ; CONTINUE PROCESSING
* BACK UP TO PREVIOUS FRAME
PI2$BACKUP:
CALL BOI$CHECK ; AT BEGINNING OF INFORMATION?
JNZ PI2$BACK ; CONTINUE IF NOT
JMP 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
*
* 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?
JNZ 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
JZ LOAD$FCB$FILL
CPI ' '+1 ; DONE IF < <SP>
JC LOAD$FCB$FILL
CALL CAPS ; CAPITALIZE
CALL CHAR$OUT ; PRINT FILE NAME AND TYPE
STAX D ; STORE CHAR
INX D ; PT TO NEXT
DCR B ; COUNT DOWN
JNZ 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 <SP>
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,' ' ; <SP> FILL REST OF FCB
STAX D ; STORE <SP>
INX D ; PT TO NEXT
DCR B ; COUNT DOWN
JNZ 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
JMP GORET
*
* RETURN TO PREVIOUS HELP LEVEL
*
LEVEL$RETURN:
LDA HELP$LEVEL ; ARE WE AT THE LOWEST LEVEL?
ORA A ; 0=YES
JNZ 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
JZ GORET$NAME0
CALL CHAR$OUT ; PRINT FILE NAME
DCR B ; DONE?
JNZ GORET$NAME
JMP GORET$NAME1
GORET$NAME0:
DCR B ; COUNT DOWN
JZ GORET$NAME1
INX H ; SKIP NEXT SPACE
JMP 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
DCR B ; COUNT DOWN
JNZ 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?
JZ 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
JC PDEC2
INR C ; INCREMENT VALUE
JMP PDEC1
PDEC2:
ADD B ; ADD POWER BACK IN
MOV B,A ; SAVE A IN B
LDA LD$SPACE ; GET LEADING <SP> FLAG
ORA A ; NON-ZERO=PRINT
JNZ PDEC3
MOV A,C ; GET DIGIT
STA LD$SPACE ; NEW FLAG
ORA A ; ZERO?
JNZ PDEC3 ; PRINT BYTE IN C
MVI A,' ' ; PRINT LEADING SPACE
JMP PDEC4
PDEC3:
MOV A,C ; GET VALUE
ADI '0' ; CONVERT TO ASCII
PDEC4:
CALL CHAR$OUT ; PRINT CHAR
MOV A,B ; RESTORE A
RET
*******************************************************
* USQ support code *
* Added 10/12/83 by Dave Rand *
*******************************************************
eof: equ 1ah
dle: equ 090h
;this is start of baseline USQ code
usq: xra a ;force init char read
sta numlft
sta rcnt ;and zero repeats
lhld lastmem
shld sob
shld eob
call getw
usq1: call getw ;get cksum, and store
shld filecrc
usq2: call get1
jnz help$exit
ora a
jnz usq2
usq3a: call getw
shld numvals
lxi d,258
call cmpdehl
jc usq3b
call errext
db 13,10,'Files has illegal decode size. Aborting.',0
usq3b: lxi d,table
usq4: shld max
mov a,h
ora l
jz usq5
push d
call getw
pop d
xchg
mov m,e
inx h
mov m,d
inx h
push h
call getw
xchg
pop h
mov m,e
inx h
mov m,d
inx h
xchg
lhld max
dcx h
jmp usq4
usq5: lxi h,0
usq6: push h
call getnxt
pop h
jnz usq8
mov e,a
mvi d,0
dad d
push h
push psw
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
pop psw
mov m,a
inx h
shld next$adr
pop h
jmp usq6
usq8: xchg
lhld filecrc
call cmpdehl
usq9: rz
call ilprt
db 13,10,'ERROR - Checksum error in file ',0
jmp help$exit
errext: pop h
mov a,m
ora a
jz help$exit
inx h
push h
call conout
jmp errext
conout: ani 127
mov e,a
mvi c,2
call bdos
ret
cmpdehl: mov a,h
cmp d
rnz
mov a,l
cmp e
ret
ilprt: pop h
mov a,m
ora a
inx h
push h
rz
call conout
jmp ilprt
get1: lhld eob
xchg
lhld sob
call cmpdehl
jz get1r
mov a,m
inx h
shld sob
cmp a
ret
get1r: mvi a,'.'
call conout
lhld lastmem
shld sob
shld eob
get1r1: push h
xchg
mvi c,26
call bdos
lxi d,fcb
mvi c,20
call bdos
pop h
ora a
jnz get1r2
lxi d,128
dad d
xchg
lhld endmem
call cmpdehl
xchg
jnc get1r1
get1r2: shld eob
xchg
lhld sob
call cmpdehl
jnz get1
mvi a,255
ora a
ret
getw: call get1
jnz badr
push psw
call get1
jnz badr
mov h,a
pop psw
mov l,a
ret
badr: call ilprt
db 13,10,'Premature EOF on file... aborted.',0
jmp 0
getnxt: lda rcnt ;see if in the middle of
ora a ;repeat sequence...
jz getn7
dcr a
sta rcnt
lda last
cmp a
ret
getn7: call getn4
cpi dle
jnz getn5
call getn4
ora a
jnz getn6
mvi a,dle ;dle is encoded as dle,0
cmp a
ret
getn6: dcr a
dcr a
sta rcnt
lda last
cmp a
ret
getn5: sta last
cmp a
ret
getn4: lxi d,0 ;pointer @ sot
lda char
mov c,a
getn1: lda numlft
ora a
jnz getn2
push d
call get1
jnz badr
pop d
mov c,a
mvi a,8
getn2: dcr a
sta numlft
mov a,c
rrc
mov c,a
lxi h,table
jnc getn3
inx h
inx h ;add 2 to point to right node
getn3: dad d
dad d
dad d
dad d ;ok.. pointing close to right plc..
mov e,m
inx h
mov d,m
mov a,d
ani 128
jz getn1
mov a,c
sta char
mov a,d
cpi 254 ;is special eof?
mvi a,eof
jz geteof ;yup
mov a,e
cma
cmp a
ret
geteof: pop h
ora a
ret
;end of baseline USQ code
*********************************************************
* MESSAGE AND BUFFER SECTION *
*********************************************************
HELPMS:
DB 'HELP Version ',(VERS/10)+'0','.',(VERS MOD 10)+'0',CR,LF,'$'
SELECTMS:
DB CR,LF,' HELP File Selections are --',CR,LF,'$'
DEFFN:
DB 0,'HELP '
DEFTYP:
DB 'HLP'
ENDMS:
DB 'EOI '
PAGEMS:
DB '^C=CP/M $' ; 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 'CR=Next $'
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,'$'
CTRLZERR:
DB CR,LF,'HELP ERROR -- HELP File NOT Terminated by ^Z',CR,LF,'$'
LEVEL$MESSAGE:
DB 'Level $'
LEVEL2$MESSAGE:
DB '/ $'
LEVEL3$MESSAGE:
DB ': $'
PROMPT1$MESSAGE:
DB 'Type ^C=CP/M$'
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 $'
lastmem: dw buff
endmem: dw buff+127
sob: dw buff
eob: dw buff
CUR$DISK:
DS 1 ; NUMBER OF CURRENT DISK IF CHANGED OR 0FFH=NO CHANGE
CUR$USER:
DS 1 ; NUMBER OF CURRENT USER IF CHANGED OR 0FFH=NO CHANGE
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
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
numlft: ds 1
rcnt: ds 1
filecrc:ds 2
last: ds 1
char: ds 1
numvals:ds 2
max: ds 2
table: ds 258*4
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
*
* DEFAULT HELP MESSAGE
*
HELP$BUF:
DB ':The HELP Subsystem for Online Documentation'
DB CR,LF,' This is HELP, the Online Documentation Subsystem.'
DB CR,LF,'The purpose of HELP is to allow the user to '
DB 'interactively'
DB CR,LF,'query the *.HLP files of the system in order to receive'
DB CR,LF,'information summaries on various aspects of the user''s'
DB CR,LF,'working environment, such as the language systems he is'
DB CR,LF,'using and certain subsystems available to him.'
DB CR,LF,LF,' When the user types ''HELP'', a search is done'
DB CR,LF,'for the file ''HELP.HLP''. If found, the contents of'
DB CR,LF,'this HELP File is displayed to the user; if not found,'
DB CR,LF,'the HELP Information you are now reading is displayed.'
DB CR,LF,LF,' If the user desires information on a specific'
DB CR,LF,'topic and he has a HELP File of that name (ie, CPM.HLP'
DB CR,LF,'is a HELP File on CP/M), he may issue of HELP Command'
DB CR,LF,'of the form --'
DB CR,LF,' HELP d:topic'
DB CR,LF,'where "d:" is the disk the HELP File resides on'
DB ' (optional)'
DB CR,LF,'and "topic" is the name of the HELP File (topic.HLP,'
DB CR,LF,'like CPM.HLP).'
DB CR,LF,' Please refer to the HELP File "HELP.HLP" for'
DB ' more information.'
DB CR,LF,CTRLZ ; END OF FILE
END