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
/
HJELP.LBR
/
HJELP.AQ6
/
HJELP.A86
Wrap
Text File
|
2000-06-30
|
37KB
|
1,629 lines
; --------------------------------------------------------------
; HJELP.ASM Copyright (C) 1984
; Universidad Autonoma de Puebla
;
; [HELP.xxx (SIG/M xxx.xx) Richard Conn]
; [HELP8080.ASM (SIG/M 122.03) = original model]
; [squeezed HELP files - Harold V. McIntosh, July 20, 1984]
; ["L" backs up to panel 1 - 20 Jul 84 - HVM]
; [Library files - 5 October 1984]
; --------------------------------------------------------------
CR equ 0DH
VT equ 0CH
LF equ 0AH
HT equ 09H
bdos equ 0E0H ;bdos interrupt
org 0005H
X0005 rb 0 ;memory end
org 005CH
tfcb rb 0 ;CP/M's file control block
org 0080H
tbuf rb 0 ;CP/M's I-O buffer
org 4000H
bred rb 0 ;red screen area
org 6000H
bgrn rb 0 ;green screen area
org 8000H ;blue screen area
bblu rb 0
NH equ 6 ;number of HELP file names to print per line
ND equ 10 ;maximum node depth
NS equ 9 ;bytes to save for panel markers
csiz equ 257
psiz equ 50*NS ;textpointer pushdown size
; -------------
org 0100H
; -------------
begn: mov X0D31,sp ;save stack
mov al,tfcb+1 ;TFCB+1
cmp al,' '
jz G001 ! jmp nnul ! G001:
mov dx,(offset tuto) ;'tutorial'
ferm: call mssg
gbye: mov sp,X0D31 ;save stack
mov cl,0
mov dl,0
int bdos
nnul: mov al,X0005+2
sub al,0AH
mov X0C63,al ;memory pages
mov bx,(offset nbuf+1)
mov (byte ptr [bx]),' '
xor al,al
mov X0C71,al ;level #
mov dx,(offset X08BE) ;'signon'
call mssg ;message to console
mov al,tfcb+1
cmp al,'('
jz G002 ! jmp loop ! G002:
mov bx,(offset tbuf)
mov ch,[bx]
pushf ! inc bx ! popf
xchg dx,bx
mov bx,(offset obuf)
mov optr,bx
call miuc
mov (byte ptr [bx]),00
mov dx,(offset lohf) ;'loading HELP file'
call mssg
call pafr
mov bx,(offset nbuf+1)
mov al,[bx]
cmp al,' '
jz G003 ! jmp ymbr ! G003:
mov dx,(offset tfcb+1)
mov ch,8
call miuc
call phlp
jmp loop
ymbr: mov bx,(offset nbuf+9)
mov al,[bx]
cmp al,' '
jnz G004 ! call phlp ! G004:
; Loop.
loop: mov sp,X0D31 ;stack
mov bx,(offset tfcb+9)
mov al,[bx]
cmp al,' '
jnz G005 ! call phlp ! G005:
mov bx,(offset tfcb) ;TFCB
mov (byte ptr [bx]),000H
mov dx,(offset 000CH)
add bx,dx
; Zero out tail of FCB.
mov ch,018H ;24
X01C9: mov (byte ptr [bx]),000H
pushf ! inc bx ! popf
dec ch
jz G006 ! jmp X01C9 ! G006:
mov bx,(offset 0FFFFH)
mov mlen,bx
ldfi: call opef
call sefl
mov (byte ptr [bx]),1AH ;^Z
call desq
jmp gogo
sefl: mov bx,(offset X0D33) ;beginning of free memory
sefm: mov al,X0C63
cmp al,bh
jnz G007 ! jmp X04D1 ! G007: ;'not enough room'
call rerb
jnc G008 ! jmp sefn ! G008:
mov [bx],al
pushf ! inc bx ! popf
jmp sefm
sefn: mov X0C6E,bx ;ptr end of text
ret
; ------------------------------------
; opef will open file even within .LBR
; ofil will open a normal file
; Test for .LBR file.
opef: mov al,nbuf+1
cmp al,' '
jnz G009 ! jmp ofil ! G009:
; -----------------------------------------
; Open a .LBR file to the member specified
; at nbuf+1 of the .LBR file referenced by
; tfcb. Termination results if either item
; cannot be found, otherwise the next read
; will pick up the desired member.
; ----------------------------------------
; Open .LBR file, read first record.
olbr: mov cl,15 ;(0F) open file
mov dx,(offset tfcb)
int bdos
inc al
jz G010 ! jmp fopn ! G010:
mov dx,(offset nlib) ;'requested library not found'
jmp ferm ;send message to console
fopn: mov bx,(offset tfcb+32)
mov (byte ptr [bx]),00
mov bx,(offset 0000)
mov mctr,bx ;counter for tbuf
pushf ! dec bx ! popf
mov mlen,bx ;length (records) of member
call afil ;fill "A" buffer
mov bx,abff+14 ;length of LBR dir
mov mlen,bx ;length (records) of member
add bx,bx
add bx,bx
mov rlen,bx ;length (32-byte lines) of directory
; Library member was requested, so look it up in directory.
tmem: mov bx,rlen ;length (32-byte lines) of directory
pushf ! dec bx ! popf
mov rlen,bx ;length (32-byte lines) of directory
mov al,bh
or al,bl
jz G011 ! jmp tmen ! G011:
mov dx,(offset nfil) ;'requested file not present'
call ferm ;message to console
tmen: call afil ;read a directory line
mov ch,11
mov dx,(offset abuf+1)
mov bx,(offset nbuf+1) ;member name buffer
call ciuc ;block compare
jz G012 ! jmp tmem ! G012:
; Record length and whether 'Q' in extension.
mov bx,abff+14
mov mlen,bx ;length (records) of member
mov bx,(offset dens) ;z/nz=un/squeezed
mov (byte ptr [bx]),0
mov al,abuf+10
cmp al,'Q'
jz G013 ! jmp sefi ! G013:
dec (byte ptr [bx])
; Advance to the proper section of the library.
; This is not an elegant way to do it, but it avoids
; computing with CP/M extents and record sizes.
sefi: mov cl,15 ;(0F) open file
mov dx,(offset tfcb)
int bdos
xor al,al
mov tfcb+32,al
; Skip up to (but don't read) beginning of member.
sefj: mov bx,abff+12
mov al,bh
or al,bl
jnz G014 ! jmp sefk ! G014:
pushf ! dec bx ! popf
mov abff+12,bx
mov cl,20 ;(14) read one record
mov dx,(offset tfcb)
int bdos
jmp sefj
sefk: mov bx,(offset 0000)
mov mctr,bx
ret
; Fill the "A" buffer, which holds .LBR directory lines.
afil: mov cl,20H
mov bx,(offset abuf) ;"A" buffer = line of LBR dir
afim: call rerb
mov [bx],al
pushf ! inc bx ! popf
dec cl
jz G015 ! jmp afim ! G015:
ret
; Read a byte from tbuf, replenishing as necessary.
; Carry signifies End of File.
rerb: push bx
mov bx,mctr ;counter for tbuf
mov al,bh
or al,bl
stc
jnz G016 ! call rerx ! G016: ;read one record
cmc
pushf ! dec bx ! popf
mov mctr,bx ;counter for tbuf
mov bx,mptr ;pointer for tbuf
mov al,[bx]
pushf ! inc bx ! popf
mov mptr,bx ;pointer for tbuf
pop bx
ret
; Read another record, but don't read past the number
; allocated to the member. Likewise, we have to be careful
; about an ASCII file which ends exactly on a record boundary.
rerx: mov bx,mlen ;length (records) of member
mov al,bh
or al,bl
jnz G017 ! jmp rery ! G017:
pushf ! dec bx ! popf
mov mlen,bx ;length (records) of member
push cx
push dx
mov cl,20 ;(14) read one record
mov dx,(offset tfcb)
int bdos
pop dx
pop cx
or al,al
jz G018 ! jmp rery ! G018:
mov bx,(offset tbuf)
mov mptr,bx ;pointer for tbuf
mov bx,(offset 0080H)
stc
ret
; Squeezed files should end with a special end
; of file marker (non-1-byte 100H), which has to be seen
; to terminate the file. ASCII files normally terminate with
; a ^Z, but this may be implicit if the file exactly fills a
; record.
rery: mov bx,(offset tbuf)
mov mptr,bx
mov (byte ptr [bx]),1AH ;^Z
mov bx,(offset 0001H)
stc
cmc
ret
; Open an ordinary file. If not found, try for a squeezed
; version instead.
ofil: mov bx,(offset 0000)
mov mctr,bx
pushf ! dec bx ! popf
mov mlen,bx
xor al,al
mov tfcb+32,al
mov dens,al
ofim: mov dx,(offset tfcb) ;TFCB
mov cl,15 ;(0F) open file
int bdos ; B D O S
inc al
jz G019 ! ret ! G019:
mov bx,(offset tfcb+10)
mov al,[bx]
mov (byte ptr [bx]),'Q'
cmp al,[bx]
jz G020 ! jmp ofim ! G020:
mov dx,(offset nfil) ;'no file'
jmp ferm
; ------------------------
; Decide whether it is a squeezed file.
desq: mov bx,(offset X0D33)
mov tptr,bx ;text pointer
mov xptr,bx ;ptr to bgn of HELP file
mov bx,(offset dens) ;z/nz = normal/squeezed file
mov (byte ptr [bx]),0
mov bx,(offset wflg) ;z/nz = no/byte left waiting by abyt
mov (byte ptr [bx]),0
call gbyt ;one byte, direct or through onsq
cmp al,076H
jz G021 ! jmp unjj ! G021:
call gbyt ;one byte, direct or through onsq
cmp al,0FFH
jnz G022 ! jmp unii ! G022:
unjj: mov bx,(offset X0D33)
mov tptr,bx ;text pointer
ret
; Squeezed, so go through initialization
unii: mov bx,(offset rcnt) ;repetition count
mov (byte ptr [bx]),0
mov bx,(offset roco) ;bit rotation counter
mov (byte ptr [bx]),1
; The "squeezed" marker is followed by a two-byte checksum,
; which is the simple sum of all the one-byte characters in
; the source file, carried as a two byte sum modulo 2**16.
rchk: call iwor ;fetch two bytes from input stream
mov cksm,bx ;checksum
; Unsqueezed file name. It is an ASCII sequence, may be lower
; case if SQ.COM received it in response to a prompt, ending
; with a zero byte.
luup: call gbyt ;fetch one byte from input stream
or al,al
jz G023 ! jmp luup ! G023:
; Load code dictionary. It is preceded by its two-byte length,
; and consists of a series of pairs of two-byte addresses. For
; each bit in the code, select the first element (0) or the
; second (1) element of the pair. If the pair is positive, it
; is the table entry (code + 4*index) at which to continue with
; the next bit. If the pair is negative, it is the complement
; of the coded ASCII character (low order byte except for [end]).
ldic: call iwor ;fetch two bytes from input stream
add bx,bx
add bx,bx
xchg dx,bx
mov bx,tptr ;text pointer
mov cptr,bx ;Huffman code table
add bx,dx
mov tptr,bx ;text pointer
mov xptr,bx ;ptr to bgn of HELP file
mov bx,(offset dens)
mov (byte ptr [bx]),0FFH
ret
; Scan the HELP text to find and record the section headings.
gogo: mov bx,(offset pudl)
mov pptr,bx ;pushdown pointer
mov bx,(offset mopt)
mov (byte ptr [bx]),'A' ;A, not @, to make <cmp m, jnc> work
call abyt ;lookahead one byte
cmp al,':'
jnz G024 ! jmp gogu ! G024:
gugu: call rbyt ;fetch one byte
cmp al,LF
jz G025 ! jmp gigi ! G025:
call rbyt ;fetch one byte
cmp al,':'
jnz G026 ! jmp gege ! G026:
gigi: cmp al,1AH
jnz G027 ! jmp gogu ! G027:
jmp gugu
gege: call pupu
mov bx,(offset mopt) ;maximum option
inc (byte ptr [bx])
jmp gugu
gogu: mov bx,pptr ;pushdown pointer
mov zptr,bx ;ptr to bgn of info sect
mov bx,xptr ;ptr to bgn of HELP file
mov tptr,bx ;text pointer
mov bx,(offset roco) ;bit rotation counter
mov (byte ptr [bx]),1
mov bx,(offset wflg) ;z/nz = no/byte left waiting by abyt
mov (byte ptr [bx]),0
; Display menu. Here we distinguish between a simple HELP
; file which begins with a colon and has only one section,
; and an indexed HELP file, which starts out with a list of
; section descriptors.
X0342: mov sp,X0D31 ;stack
mov al,000H
mov X0C72,al ;panel #
call abyt ;lookahead one byte
cmp al,'!'
jnc G028 ! jmp xxxx ! G028:
cmp al,':'
jz G029 ! jmp X036A ! G029: ;show menu, request option
call rbyt ;fetch one byte
xxxx: call X05E5 ;initialize new section
mov al,X0C71 ;level #
or al,al
jnz G030 ! jmp gbye ! G030: ;return to CP/M
jmp X07ED ;go up one level
; Return to CP/M
; Show menu, request option.
X036A: call X058D ;run through the menu
push cx
call crlf ;CR,LF
call X0859 ;type level I.D.
mov dx,(offset X0C19) ;'Type [^C]'
call mssg ;message to console
mov dx,(offset X0C27) ;'Type [level or root]'
mov al,X0C71 ;level #
or al,al
jnz G031 ! jmp X0387 ! G031:
call mssg ;message to console
X0387: mov dx,(offset X0C37) ;'Enter Selection'
call mssg ;message to console
pop cx
call X046B ;read char from console
cmp al,003H ;^C
jnz G032 ! jmp gbye ! G032: ;return to CP/M
cmp al,'.'
jnz G033 ! jmp X07E1 ! G033: ;back to root
cmp al,'^'
jnz G034 ! jmp X07ED ! G034: ;go up one level
lahf ! xchg ah,al ! push ax ! xchg ah,al
call crlf ;CR,LF
pop ax ! xchg ah,al ! sahf
mov bx,(offset mopt) ;maximum option
cmp al,[bx]
jc G035 ! jmp X03AE ! G035:
sub al,'@'
jnc G036 ! jmp X03AE ! G036:
jnz G037 ! jmp X03AE ! G037:
call anth ;access nth option
call X05E5 ;initialize new section
jmp X036A ;show menu, request option
X03AE: mov dx,(offset X0AC6) ;'Invalid Response'
call mssg ;message to console
jmp X036A ;show menu, request option
; Insert extension .HLP
phlp: mov (byte ptr [bx]),'H'
pushf ! inc bx ! popf
mov (byte ptr [bx]),'L'
pushf ! inc bx ! popf
mov (byte ptr [bx]),'P'
ret
; Read a character from the console.
X046B: push cx
push dx
push bx
mov cl,1 ;(01) console input
int bdos ; B D O S
pop bx
pop dx
pop cx
lahf ! xchg ah,al ! push ax ! xchg ah,al
call crlf ;CR,LF
pop ax ! xchg ah,al ! sahf
X047B: and al,07FH ;upper case fold
cmp al,'a'
jnc G038 ! ret ! G038:
cmp al,'{'
jc G039 ! ret ! G039:
and al,05FH
ret
; CR, LF.
crlf: mov al,CR
call cona ;char to console
mov al,LF
jmp cona ;char to console
; Character to console.
cona: lahf ! xchg ah,al ! push ax ! xchg ah,al
push cx
push dx
push bx
mov cl,2 ;(02) console output
mov dl,al
int bdos ; B D O S
pop bx
pop dx
pop cx
pop ax ! xchg ah,al ! sahf
ret
; Message to Console.
mssg: push cx
push dx
push bx
mov cl,9 ;(09) print string to $
int bdos ; B D O S
pop bx
pop dx
pop cx
ret
; Type file name.
tyfn: mov al,[bx]
cmp al,' '
jnz G040 ! ret ! G040:
mov ch,8
call tyfo
mov al,[bx]
cmp al,' '
jnz G041 ! ret ! G041:
mov al,'.'
call cona
mov ch,3
tyfo: mov al,[bx]
pushf ! inc bx ! popf
cmp al,' '
jz G042 ! call cona ! G042:
dec ch
jz G043 ! jmp tyfo ! G043:
ret
; Compare B bytes between (HL) and (DE)
ciuc: xchg dx,bx ! mov al,[bx] ! xchg dx,bx
cmp al,[bx]
jz G044 ! ret ! G044:
pushf ! inc dx ! popf
pushf ! inc bx ! popf
dec ch
jz G045 ! jmp ciuc ! G045:
ret
; Move B bytes from (DE) to (HL).
miuc: xchg dx,bx ! mov al,[bx] ! xchg dx,bx
mov [bx],al
pushf ! inc dx ! popf
pushf ! inc bx ! popf
dec ch
jz G046 ! jmp miuc ! G046:
ret
; Move B bytes from (HL) to (DE)
mduc: pushf ! dec bx ! popf
pushf ! dec dx ! popf
mov al,[bx]
xchg dx,bx ! mov [bx],al ! xchg dx,bx
dec ch
jz G047 ! jmp mduc ! G047:
ret
; Initialize pudl.
izpu: mov ch,NS
mov dx,(offset lach)
mov bx,zptr ;ptr to bgn of info sect
call miuc
mov yptr,bx ;zptr+NS
mov pptr,bx ;pushdown pointer
mov bx,(offset X0C72) ;panel #
mov (byte ptr [bx]),1
ret
; Restore to the head of pudl.
rspu: mov ch,NS
mov bx,yptr ;zptr+NS
mov pptr,bx ;pushdown pointer
mov dx,(offset lach+NS)
call mduc
mov bx,(offset X0C72) ;panel #
mov (byte ptr [bx]),0
ret
; Access nth option.
anth: mov dl,al
mov dh,0
mov bl,dl
mov bh,dh
add bx,bx
add bx,bx
add bx,bx
add bx,dx
mov dx,(offset pudl)
add bx,dx
mov dx,(offset lach+NS)
mov ch,NS
call mduc
mov bx,zptr ;ptr to bgn of info sect
mov pptr,bx ;pushdown pointer
mov bx,(offset X0C72)
mov (byte ptr [bx]),1
ret
; Push state onto pudl.
pupu: mov bx,pptr ;pushdown pointer
mov dx,(offset pudl+psiz)
mov al,bl
sub al,dl
mov al,bh
sbb al,dh
jc G048 ! ret ! G048:
mov ch,NS
mov dx,(offset lach)
call miuc
mov pptr,bx ;pushdown pointer
mov bx,(offset X0C72) ;panel #
inc (byte ptr [bx])
ret
; Pop state from pudl.
popu: mov bx,zptr
xchg dx,bx
mov bx,pptr ;pushdown pointer
mov al,dl
sub al,bl
mov al,dh
sbb al,bh
jc G049 ! ret ! G049:
mov ch,NS
mov dx,(offset lach+NS)
call mduc
mov pptr,bx ;pushdown pointer
mov bx,(offset X0C72) ;panel #
mov al,[bx]
or al,al
jnz G050 ! ret ! G050:
dec (byte ptr [bx])
ret
X04D1: mov dx,(offset X0BDC) ;'Not Enough Room'
jmp ferm
onsq: mov al,rcnt ;repetition count
or al,al
jz G051 ! jmp onsr ! G051:
call dnch ;decode next character
jnc G052 ! jmp vchk ! G052: ;verify the checksum
cmp al,090H ;repeat last character
jz G053 ! jmp onsu ! G053: ;normal character
call dnch ;decode next character
or al,al
jnz G054 ! jmp onss ! G054:
dec al
onsr: dec al
mov rcnt,al ;repetition count
mov al,lach
jmp achk
onss: mov al,090H
jmp achk
onsu: mov lach,al ;last character typed
jmp achk
; Decode next character.
dnch: mov bx,cptr ;Huffman code table
dncr: call ibit ;read next bit
jc G055 ! jmp dncs ! G055: ;skip for 1, stay for 0
pushf ! inc bx ! popf
pushf ! inc bx ! popf
dncs: mov dl,[bx] ;get next offset
pushf ! inc bx ! popf
mov dh,[bx]
mov al,dh
cmp al,0FEH ;FEFF means [end]
jnz G056 ! jmp dnct ! G056:
or al,al
js G057 ! jmp dncu ! G057: ;p means new offset
mov al,dl ;m means complemented char
not al
stc
cmc
ret
dnct: stc ;flag [end] with carry bit
ret
; Calculate <code>+4*<offset>.
dncu: mov bx,cptr ;Huffman code table
add bx,dx
add bx,dx
add bx,dx
add bx,dx
jmp dncr
; Read one bit at a time.
ibit: push bx
mov bx,(offset roco) ;bit rotation counter
dec (byte ptr [bx])
jz G058 ! jmp ibiu ! G058:
mov (byte ptr [bx]),8
call ibyt ;fetch one byte from input stream
mov roby,al ;rotating byte
ibiu: mov al,roby ;rotating byte
rcr al,1
mov roby,al ;rotating byte
pop bx
ret
; Read one word.
iwor: call ibyt ;fetch one byte from input stream
mov bl,al
push bx
call ibyt ;fetch one byte from input stream
pop bx
mov bh,al
ret
; Accumulate checksum.
achk: mov bx,(offset cksm)
mov ch,al
mov al,[bx]
sub al,ch
mov [bx],al
pushf ! inc bx ! popf
mov al,[bx]
sbb al,0
mov [bx],al
mov al,ch
stc
cmc
ret
; Verify the checksum.
vchk: mov bx,cksm ;checksum
mov al,bl
or al,bh
stc
jnz G059 ! ret ! G059: ;return to CP/M
mov dx,(offset chno) ;'Checksum failure.'
jmp ferm ;fatal error message
abyt: push bx
mov bx,(offset wflg) ;z/nz = no/byte left waiting by abyt
mov al,[bx]
or al,al
jnz G060 ! jmp abyy ! G060:
mov al,wbyt ;byte left waiting by abyt
jmp abyr
abyy: dec (byte ptr [bx])
call gbyt ;one byte, direct or through onsq
mov wbyt,al ;byte left waiting by abyt
abyr: pop bx
ret
rbyt: mov al,wflg ;z/nz = no/byte left waiting by abyt
or al,al
jnz G061 ! jmp gbyt ! G061: ;one byte, direct or through onsq
mov al,0
mov wflg,al ;z/nz = no/byte left waiting by abyt
mov al,wbyt ;byte left waiting by abyt
ret
gbyt: mov al,dens ;one byte, direct or through onsq
or al,al
jnz G062 ! jmp ibyt ! G062:
push bx
call onsq ;one byte from squeezed file
pop bx
ret
ibyt: push bx ;fetch byte from the input stream
push dx
mov bx,X0C6E ;ptr end of text
xchg dx,bx
mov bx,tptr ;text pointer
mov al,bl
sub al,dl
mov al,bh
sbb al,dh
mov al,[bx]
pushf ! inc bx ! popf
mov tptr,bx ;text pointer
cmc
pop dx
pop bx
ret
; Type line, solicit option.
X04DA: call rbyt ;fetch one byte
cmp al,CR
jnz G063 ! jmp X04F4 ! G063: ;type options at bottom of panel
cmp al,LF
jnz G064 ! jmp X04F5 ! G064: ;type options at bottom of panel
cmp al,01AH ;^Z
jnz G065 ! jmp X04F5 ! G065: ;type options at bottom of panel
call cona ;char to console
jmp X04DA ;type line, solicit option
; Type the options at bottom of panel.
; Entry point according to how line ended.
X04F4: call rbyt ;decomission following LF
X04F5: call crlf ;CR,LF
mov bx,(offset X0C6B) ;console remaining lines
dec (byte ptr [bx])
jz G066 ! ret ! G066:
; Solicit options (without marking or incrementing line).
X0504: call X0859 ;type level I.D.
mov dx,(offset X097A) ;'^C = Exit'
call mssg ;message to console
X050D: mov dx,(offset X0983) ;'[level, root]'
mov al,X0C71 ;level #
or al,al
jnz G067 ! jmp X0521 ! G067:
call mssg ;message to console
X0521: mov dx,(offset X0993) ;'[option list]'
call mssg ;message to console
call X046B ;read char from console
mov char,al ;char read from console
cmp al,'M'
jz G068 ! jmp pnla ! G068:
jmp X0342 ;display menu
pnla: cmp al,003H ;^C
jz G069 ! jmp pnlb ! G069:
jmp gbye ;return to CP/M
pnlb: cmp al,'P'
jz G070 ! jmp pnlc ! G070:
jmp X06FE ;fulfil PRINT request
pnlc: cmp al,'.'
jz G071 ! jmp pnld ! G071:
jmp X07E1 ;back to root
pnld: cmp al,'^'
jz G072 ! jmp pnle ! G072:
jmp X07ED ;go up one level
pnle: cmp al,'L'
jz G073 ! jmp pnlf ! G073:
call popu
call popu
jmp pnlg
pnlf: cmp al,'S'
jz G074 ! jmp pnlg ! G074:
call rspu ;restore start of info section
pnlg: call pupu ;save reference to section head
call X0587 ;reset line count
jmp crlf ;CR,LF
; Reset line count.
X0587: mov al,23 ;lines per screen panel
mov X0C6B,al ;console remaining lines
ret
; Run through the menu.
X058D: mov al,000H
mov X0C72,al ;panel #
mov bx,xptr ;ptr to bgn of HELP file
mov tptr,bx ;text pointer
mov bx,(offset roco) ;bit rotation counter
mov (byte ptr [bx]),1
mov bx,(offset wflg) ;z/nz = no/byte left waiting by abyt
mov (byte ptr [bx]),0
call X0587 ;reset line count
mov bx,(offset X0C6B) ;console remaining lines
dec (byte ptr [bx])
mov al,'A'
mov X0C68,al ;option letter
mov dx,(offset X0954) ;'Selections are ...'
call mssg ;message to console
mov cl,000H
X05AC: call abyt ;lookahead one byte
cmp al,':'
jnz G075 ! jmp X05D4 ! G075: ;finish panel w/CR,LF's
cmp al,01AH ;^Z
jnz G076 ! jmp gbye ! G076: ;return to CP/M
inc cl
mov al,X0C68 ;option letter
call cona ;char to console
inc al
mov X0C68,al ;option letter
mov al,'.'
call cona ;char to console
mov al,' '
call cona ;char to console
call X04DA ;type line, solicit option
jmp X05AC
; Finish out panel with CR, LF's.
X05D4: mov al,X0C6B ;console remaining lines
mov ch,al
or al,al
jnz G077 ! ret ! G077:
X05DD: call crlf ;CR,LF
dec ch
jz G078 ! jmp X05DD ! G078:
ret
; A loop which will print out an information section. It calls
; X04DA, which will count out lines as it types them. If the
; line it has just typed is the last one of the panel, it
; will pause for the panel to be read, having solicited some
; indication of whether it should procede, repeat the last panel,
; go back to the beginning, or go back to the menu.
X05E5: call X075D ;is section disk file?
call izpu
call X0587 ;reset line count
X05FA: call abyt ;lookahead one byte
cmp al,01AH ;^Z
jnz G079 ! jmp X0624 ! G079: ;mark panel, type legend, read option
cmp al,':'
jnz G080 ! jmp X0624 ! G080: ;mark panel, type legend, read option
cmp al,VT ;form feed
jnz G081 ! jmp X05FB ! G081:
call X04DA
jmp X05FA
X05FB: call rbyt ;fetch one byte
mov al,X0C6B ;console remaining lines
X061A: lahf ! xchg ah,al ! push ax ! xchg ah,al
call X04F5 ;type options at bottom of panel
pop ax ! xchg ah,al ! sahf
dec al
jz G082 ! jmp X061A ! G082:
jmp X05FA
; Mark panel, type legend, select option.
X0624: call rbyt ;fetch one byte
X0628: call crlf ;CR,LF
mov bx,(offset X0C6B) ;console remaining lines
dec (byte ptr [bx])
jz G083 ! jmp X0628 ! G083:
X0635: call X0859 ;type level I.D.
mov dx,(offset X0976) ;'EOI & ^C'
call mssg ;message to console
call X050D
mov al,char ;char read from console
cmp al,'L'
jnz G084 ! jmp X05FA ! G084:
cmp al,'S'
jnz G085 ! jmp X05FA ! G085:
cmp al,'P'
jnz G086 ! jmp X05FA ! G086:
ret
; Send line to LST:, check for interrupt request.
X06B3: call rbyt ;fetch one byte
cmp al,CR
jnz G087 ! jmp X06CE ! G087: ;list CR, LF's at end of line
cmp al,LF
jnz G088 ! jmp X06CF ! G088: ;list CR, LF's at end of line
cmp al,01AH ;^Z
jnz G089 ! jmp X06CF ! G089: ;list CR, LF's at end of line
call X06E4 ;list output, read status
jz G090 ! jmp X06B3 ! G090: ;line to LST:
ret
; Type CR, LF at end of line. Entry point according
; to whether CR, LF, or ^Z was encountered.
X06CE: call rbyt ;decomission following LF
X06CF: mov al,CR
call X06E4 ;list output, read status
jnz G091 ! ret ! G091: ;to catch a ^C between CR, LF
mov al,LF
X06E4: push bx
push dx
push cx
mov dl,al
mov cl,5 ;(05) list output
int bdos ; B D O S
mov dl,0FFH
mov cl,6 ;(06) direct console I/O
int bdos ; B D O S
pop cx
pop dx
pop bx
cmp al,003H
ret
; Respond to PRINT request.
X06FE: mov dx,(offset X09DE) ;'Set Top-of-Form'
call mssg ;message to console
xor al,al
mov X0C61,al ;z/nz = panel/section (P)
call popu
call pupu
call X046B ;read char from console
cmp al,003H ;^Z
jnz G092 ! jmp X071B ! G092:
cmp al,'S'
jnz G093 ! jmp X0718 ! G093:
call rspu
call pupu
mov al,0FFH
mov X0C61,al ;z/nz = panel/section (P)
X0718: call X0730
X071B: call popu
jmp pnlg
X0730: mov dx,(offset X09B2) ;'Printing in Progress ...'
call mssg ;message to console
call X0587 ;reset line count
X0739: call X06B3 ;line to LST:
cmp al,003H ;^C
jnz G094 ! ret ! G094:
call abyt ;lookahead one byte
cmp al,01AH ;^Z
jnz G095 ! ret ! G095:
cmp al,':'
jnz G096 ! ret ! G096:
cmp al,VT ;Form Feed
jnz G097 ! call X06CF ! G097: ;list CR, LF's at end of line
mov al,X0C61 ;z/nz = panel/section (P)
or al,al
jz G098 ! jmp X0739 ! G098:
mov bx,(offset X0C6B) ;console remaining lines
dec (byte ptr [bx])
jz G099 ! jmp X0739 ! G099:
ret
; Check whether section is a disk file.
X075D: call abyt ;lookahead one byte
cmp al,':'
jz G100 ! ret ! G100:
call rbyt
mov al,X0C71 ;level #
cmp al,ND ;maximum node depth
jz G101 ! jmp X0776 ! G101: ;read file, type name
mov dx,(offset X0B4A) ;'Node Limit'
call mssg ;message to console
jmp gbye ;return to CP/M
; Type name, read file.
X0776: call X0845 ;locate file name on stack
mov dx,(offset tfcb+1) ;TFCB+1
mov ch,11 ;bytes in file name
call miuc
mov ch,11
mov dx,(offset nbuf+1)
call miuc
mov bx,(offset X0C71) ;level #
inc (byte ptr [bx])
; If there can be several color overlays and the like,
; we have to set aside the panel defining them so that
; the space it occupies can be used for loading.
mov ch,0
mov dx,(offset 0000)
mov bx,(offset obuf)
mov optr,bx
olay: call rbyt
jnc G102 ! jmp loaz ! G102:
cmp al,1AH ;^Z
jnz G103 ! jmp loaz ! G103:
cmp al,':'
jz G104 ! jmp olax ! G104:
mov al,LF
cmp al,ch
jnz G105 ! jmp loaz ! G105:
mov al,':'
olax: mov [bx],al
mov ch,al
pushf ! inc dx ! popf
pushf ! inc bx ! popf
cmp al,':'
jz G106 ! jmp olay ! G106:
call rbyt
cmp al,':'
jz G107 ! jmp loaz ! G107:
jmp olay
loaz: xchg dx,bx
mov octr,bx
jmp colo
; Subroutine which will read out the bytes saved from
; the instruction panel when overlays are to be used.
obyt: push bx
; lhld octr
; mov a,h
; ora l
; jz obyz
; dcx h
; shld octr
mov bx,optr
mov al,[bx]
pushf ! inc bx ! popf
mov optr,bx
obyz: pop bx
ret
; Load any requested overlays.
colo: mov dx,(offset lohf) ;'Loading HELP File'
call mssg ;message to console
mov bx,(offset dest)
mov (byte ptr [bx]),' '
call pafr ;parse file reference.
jmp coov ;execute it
; Parse a file reference, and type it.
pafr: mov al,' '
mov nbuf+1,al
paff: call obyt
cmp al,' '
jnz G108 ! jmp paff ! G108:
cmp al,'('
jnz G109 ! jmp ylbr ! G109:
mov bx,(offset tfcb)
call pars
cmp al,')'
jnz G110 ! jmp wlbr ! G110:
mov bx,(offset tfcb+1)
jmp tyfn
ylbr: mov bx,(offset tfcb)
call part
wlbr: mov bx,(offset nbuf)
call part
; Insert extension .LBR if none was given.
mov bx,(offset tfcb+9)
mov al,[bx]
cmp al,' '
jz G111 ! jmp ylbs ! G111:
mov (byte ptr [bx]),'L'
pushf ! inc bx ! popf
mov (byte ptr [bx]),'B'
pushf ! inc bx ! popf
mov (byte ptr [bx]),'R'
ylbs: mov al,'('
call cona
mov bx,(offset tfcb+1)
call tyfn
mov al,')'
call cona
mov al,' '
call cona
mov bx,(offset nbuf+1)
jmp tyfn
; Check for color overlay.
coov: mov bx,(offset dest)
mov al,[bx]
mov (byte ptr [bx]),' '
cmp al,[bx]
jz G112 ! jmp coow ! G112:
call crlf
jmp loop ;loop
coow: cmp al,'R'
jz G113 ! jmp gree ! G113:
call opef
call sefl
call desq
mov bx,(offset bred) ;red screen area
call lcbf
jmp colo
gree: cmp al,'G'
jz G114 ! jmp blue ! G114:
call opef
call sefl
call desq
mov bx,(offset bgrn) ;green screen area
call lcbf
jmp colo
blue: cmp al,'B'
jz G115 ! jmp colo ! G115:
call opef
call sefl
call desq
mov bx,(offset bblu) ;blue screen area
call lcbf
jmp colo
; Load color buffer. HL designates the buffer.
lcbf: mov al,oper
cmp al,'='
jz G116 ! jmp ocbf ! G116:
ldbf: call rbyt
jnc G117 ! jmp colo ! G117:
mov [bx],al
pushf ! inc bx ! popf
jmp ldbf
ocbf: cmp al,'+'
jz G118 ! jmp xcbf ! G118:
odbf: call rbyt
jnc G119 ! jmp colo ! G119:
or al,[bx]
mov [bx],al
pushf ! inc bx ! popf
jmp odbf
xcbf: cmp al,'-'
jz G120 ! jmp colo ! G120:
xdbf: call rbyt
jnc G121 ! jmp colo ! G121:
xor al,[bx]
mov [bx],al
pushf ! inc bx ! popf
jmp xdbf
; ---------------------------------------------
; Parse disk, filename, extension. HL points to
; FCB, new characters arrive via <call obyt>.
; ---------------------------------------------
; Pass over leading blanks.
; <call part> to ignore A
; <call pars> to test A first
part: call obyt
pars: cmp al,' '
jz part
call term
jnz G123 ! ret ! G123: ;null buffer
; Insert filename field. If a disk unit is specified,
; record it in the first byte of the FCB, then try again
; for the filename. Likewise, if a destination is given,
; note it.
mov (byte ptr [bx]),0
infn: inc bx
infi: push bx
mov ch,8
call stof
call oprn
jnz dsku
mov oper,al
pop bx
mov al,[bx]
mov dest,al
call obyt
cmp al,'('
jnz infi
call obyt
jmp infi
dsku: cmp al,':'
jnz inxt
pop bx
mov al,[bx]
sub al,'@'
mov [bx],al
dec bx
call obyt
jmp infn
; Insert extension field.
inxt: inc sp
inc sp
mov ch,3
cmp al,'.'
jnz shof
call obyt
; Store field.
stof: mov [bx],al
inc bx
dec ch
jz lonf
call obyt
call term ;z=terminator
jnz stof
; Complete short field with blanks.
shof: mov (byte ptr [bx]),' '
inc bx
dec ch
jnz shof
ret
; Ignore remainder of long field.
lonf: call obyt
call term ;z=terminator
jnz lonf
ret
; Check for a field terminator (z).
; Check for an operation (z).
term: cmp al,'.'
jz G132
cmp al,' '
jz G132
cmp al,':'
jz G132
cmp al,')'
jz G132
cmp al,CR
jz G132
or al,al
jz G132
oprn: cmp al,'='
jz G132
cmp al,'+'
jz G132
cmp al,'-'
G132: ret
; ------------------------
; Go back to root.
X07E1: mov al,X0C71 ;level #
or al,al
jnz G140 ! jmp X0342 ! G140: ;display menu
mov al,000H
jmp X07FE
; Go up one level.
X07ED: mov al,X0C71 ;level #
or al,al
jz G141 ! jmp X07FD ! G141: ;revert to last level
mov dx,(offset X0BAD) ;'No Higher Level'
call mssg ;message to console
jmp X0342 ;display menu
; Revert to upper level, type name.
X07FD: dec al
X07FE: mov X0C71,al ;level #
call X0845 ;locate file name on stack
push bx
mov dx,(offset lohf) ;'Loading HELP File'
call mssg ;message to console
call tyfn ;type filename
call crlf
pop dx
mov bx,(offset tfcb+1) ;TFCB+1
mov ch,11 ;bytes in file name
call miuc
mov ch,11
mov bx,(offset nbuf+1)
call miuc
jmp loop ;loop
; Locate file name on stack.
X0845: call X084D ;HL=A*22
mov dx,(offset X0C73) ;PDL for HELP file names
add bx,dx
ret
; HL = A*22
X084D: mov bl,al
mov bh,000H
mov dl,bl
mov dh,bh
add bx,bx
add bx,bx
add bx,bx
add bx,dx
add bx,dx
add bx,dx
add bx,bx
ret
; Type level identification.
X0859: mov al,X0C71 ;level #
or al,al
jnz G142 ! jmp X0872 ! G142:
mov dx,(offset X0C0C) ;'Level 1'
call mssg ;message to console
mov al,X0C71 ;level #
call X0881 ;translate level # to ASCII
mov dx,(offset X0C13) ;'/ '
call mssg ;message to console
X0872: mov al,X0C72 ;panel #
or al,al
jnz G143 ! ret ! G143:
call X0881 ;translate level # to ASCII
mov dx,(offset X0C16) ;': '
call mssg ;message to console
ret
; Translate level number to ASCII string.
X0881: lahf ! xchg ah,al ! push ax ! xchg ah,al
xor al,al
mov X0C70,al ;z/nz = 1/2 digit number
pop ax ! xchg ah,al ! sahf
mov ch,100 ;one hundred
call X0896 ;type A as decimal number
mov ch,10 ;ten
call X0896 ;type A as decimal number
add al,'0'
jmp cona ;char to console
; Type A as decimal number.
X0896: mov cl,000H
X0898: sub al,ch
jnc G144 ! jmp X08A0 ! G144:
inc cl
jmp X0898
X08A0: add al,ch
mov ch,al
mov al,X0C70 ;z/nz = 1/2 digit number
or al,al
jz G145 ! jmp X08B6 ! G145:
mov al,cl
mov X0C70,al ;z/nz = 1/2 digit number
or al,al
jz G146 ! jmp X08B6 ! G146:
mov al,' '
jmp X08B9
X08B6: mov al,cl
add al,'0'
X08B9: call cona ;char to console
mov al,ch
ret
X08BE db 'HJELP/ICUAP/05-OCT-84',CR,LF,'$'
tuto db 'Many systems feature HELP files containing information',CR,LF
db 'about the usage or characteristics of the system itself',CR,LF
db 'or the programs which it contains. HELP files are often',CR,LF
db 'structured, and require an auxiliary program which will',CR,LF
db 'facilitate their consultation. HJELP.COM satisfies this',CR,LF
db 'requirement, even if the HELP files have been squeezed',CR,LF
db 'or have been placed in a library.',CR,LF
db ' HJELP FILE',CR,LF
db 'will display either FILE.HLP or FILE.HQP, using a menu',CR,LF
db 'of information sections and a series of prompts which',CR,LF
db 'are largely self-explanatory.',CR,LF
db ' HJELP (LIBR) FILE',CR,LF
db 'will display FILE.HLP, taken from the library LIBR.LBR.',CR,LF
db 'Finally,',CR,LF
db ' HJELP (FILE)',CR,LF
db 'will assume that FILE.HLP is a member of FILE.LBR. Such',CR,LF
db 'a construction presupposes that FILE.LBR contains many',CR,LF
db 'additional files which are referenced through FILE.HLP.',CR,LF
db 'In all cases, an explicitly given extension will be',CR,LF
db 'respected, even when it is different from the default.',CR,LF
db '$'
X0954 db CR,LF,' HELP File Selections are --',CR,LF,'$'
X0976 db 'EOI '
X097A db '^C=Exit $'
X0983 db '^=Level .=Root $'
X0993 db 'M=Menu S=Start L=Last P=Print $'
X09B2 db 'Printing in Progress -- Strike ^C to Quit $'
X09DE db 'Please Set Top-of-Form on Printer',CR,LF
db ' Strike S to Print this Screen Only,'
db ' ^C to Quit, or',CR,LF
db ' Any Other Char to Print Entire Information Section - $'
X0AC6 db CR,LF,'% -- Invalid Response',CR,LF,'$'
X0AE9 db CR,LF,'% -- EOF on HELP File',CR,LF,'$'
X0B4A db CR,LF,'% -- Node Level Limit Reached'
db ' -- Returning to CP/M',CR,LF,'$'
X0B81 db CR,LF,'% -- Invalid File Name in Load',CR,LF,'$'
X0BAD db CR,LF,'% -- No Higher Level to Return to',CR,LF,'$'
X0BDC db CR,LF,'% -- Not Enough Room for HELP File',CR,LF,'$'
X0C0C db 'Level $'
X0C13 db '/ $'
X0C16 db ': $'
X0C19 db 'Type ^C=Exit$'
X0C27 db ' ^=Level .=Root$'
X0C37 db ' or Enter Selection $'
lohf db CR,LF,'Loading HELP File $'
chno db CR,LF,'Checksum failure.$'
nlib db CR,LF,'Requested library not present.$'
rerr db CR,LF,'Read error.$'
nfil db CR,LF,'Requested file not present.$'
mlen rw 1 ;length (records) of member
rlen rw 1 ;length (32-byte lines) of directory
actr rw 1
aptr rw 1
abff rw 0 ;word version of abuf
abuf rb 32
nbuf rb 12
mctr rw 1
mptr rw 1
oper rb 1 ;color operation
dest rb 1 ;color area
octr rw 1
optr rw 1
obuf rb 80H
X0C61 rb 1 ;z/nz = panel/section (P)
X0C62 rb 1 ;user code
X0C63 rb 1 ;memory pages
X0C68 rb 1 ;option letter
X0C6B rb 1 ;console remaining lines
X0C6E rw 1 ;ptr end of text
X0C70 rb 1 ;z/nz = 1/2 digit number
X0C71 rb 1 ;level #
X0C72 rb 1 ;panel #
X0C73 rb ND*22+100 ;PDL for HELP file names/stack
X0D31 rw 1 ;save stack pointer
cksm rw 1 ;checksum
lach rb 1 ;%; last character typed S
rcnt rb 1 ;%; repetition count E
roco rb 1 ;%; rotating bit counter Q
roby rb 1 ;%; rotating byte U
dens rb 1 ;%; z/nz=normal/squeezed file E
wflg rb 1 ;%; z/nz=no/byte awaiting abyt N
wbyt rb 1 ;%; byte left waiting by abyt C
tptr rw 1 ;%; text pointer E
xptr rw 1 ;ptr to bgn of HELP file
yptr rw 1 ;zptr+NS
zptr rw 1 ;ptr to bgn of info sect
cptr rw 1 ;Huffman code table
pptr rw 1 ;pushdown pointer
mopt rb 1 ;maximum option
char rb 1 ;char read from console
pudl rb NS*50 ;pushdown for section heads
X0D33 rb 0 ;free memory
; Layout of pudl and pointers:
;
; pudl: menu
; ...
; menu
; zptr-> panel 1
; yptr-> panel 2
; ...
; pptr-> panel n
; x
; x
; x
; X0D33: x
; x
; cptr-> Huffman code
; x
; x
; xptr-> HELPfile text
; x
; x
; tptr-> x
; x
; x
end