; -------------------------------------------------------------- ; 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 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 +4*. 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 . ; --------------------------------------------- ; Pass over leading blanks. ; to ignore A ; 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