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 / ENTERPRS / CPM / UTILS / A / BSHOW32.LZH / BISHOW32.ASM < prev    next >
Assembly Source File  |  2000-06-30  |  49KB  |  1,931 lines

  1. ;
  2. ;    title    'BISHOW v3.02 - buffered bidirectional file scroll utility'
  3. ;
  4. ; Ver 3.02, 3 Nov 85, Rod Clark, Seattle WA
  5. ;       - added Wordstar cursor pad (^C now = page down).
  6. ;    - ESC exits, clears screen. Q exits, leaves screen.
  7. ;    - Wrong keys are ignored.  H = brief help. ? = help.
  8. ;    - SHORT  +  SQUEEZE  +  LIBRARY = .COM file < 2k.
  9. ;    - SHORT, no SQUEEZE, no LIBRARY = .COM file < 1k.
  10. ;    - SHORT disables setting each margin interactively
  11. ;      (the command line still sets the right margin and
  12. ;      the page length), but it does let you scroll back
  13. ;      and forth horizontally by tab stops within a file.
  14. ;      The SHORT version gives two sets of cursor keys
  15. ;      (Wordstar and CR/SP etc), but no help display.
  16. ;    - BISHOW (no filename) tells whether it works on .LBR
  17. ;      or squeezed files, or both, or just on plain files.
  18. ;    - and fixed jumbled multiple-line .LBR directory.
  19. ;    
  20. ; Ver 3.01, 15 Jan 84, Frans van Duinen, Toronto, Ont
  21. ;    - made unsqueeze message optional
  22. ;    - added library capability
  23. ;    - fixed bug in conditional assembly of CLRSCR
  24. ;
  25. ; Ver 2.09, 7 Jan 84, Frans van Duinen, Toronto, Ont
  26. ;    - Modified USQ routines for higher speed (+10%) and
  27. ;         less memory usage.
  28. ;    - made USQ code optional through conditional assembly
  29. ;    - fixed a bug introduced with 2.08 and SHORT=TRUE 
  30. ;      (resulted from ASM's inability to nest IF/ENDIF) 
  31. ;    - fixed a bug  that reset FCBEX after open, whenever
  32. ;      sector 0 was read, (this resulted in BDOS assuming that
  33. ;      the current extent, whose allocation group nos were still
  34. ;      in the FCB, was the correct one. 
  35. ;    - Changed exit to clear screen only on Q or ^C exit,
  36. ;      to leave any messages visible
  37. ;    - Made wait after clear screen a cond assembly option
  38. ;
  39. ; Ver 2.08, 2 Jan 84, Frans van Duinen, Toronto, Ont
  40. ;    - added squeezed file capability
  41. ;    - added sidewise scrolling on ^I, ^L, steps of 8
  42. ;    - Osborne support for cursor keys, clr scr & scr size
  43. ;    - Changed FILBAK rtn to recognize top of file
  44. ;    - Set up flag to avoid unnecessary re-reading of
  45. ;      top of file 
  46. ;
  47. ;    The unsqueeze code was lifted from the USQ base code
  48. ;    by Dave Rand (Edmonton, Alberta) as adapted for LTYPE1
  49. ;    by S.Kluger (El Paso,Texas)
  50. ;    The code was lifted to allow continued use of ASM.COM 
  51. ;
  52. ; Ver 1.07, 1 Aug 83, Ted H. Emigh  ...!unc!tucc!emigh
  53. ;    - added screen width specification
  54. ;    - added screen definition commands (see notes below)
  55. ;
  56. ; Ver 1.06, 2 Jul 83, Chuck Forsberg
  57. ;    - added commands for more, mince, vi familiarity.
  58. ;      Bad cmd gives help
  59. ;
  60. ; Ver 1.051, 26 June 83, Dick Mead
  61. ;    - added "?" for help on commands.
  62. ;
  63. ; Ver 1.05, 31 May 83, Bruce Ratoff
  64. ;    - added 'N' (next line) and 'P' (previous line) cmds
  65. ;    - decreased buffer from 8k to 4k (8k takes too long)
  66. ;
  67. ; Ver 1.04, 15 May 83, Keith Petersen, W8SDZ
  68. ;    - fixed bug which caused display past end-of-file
  69. ;        and added bogus eof in case none at file end
  70. ;    - added strip of high-order bit in line count routine
  71. ;    - added exit clear of any left-over keyboard character
  72. ;
  73. ; Ver 1.03, 11 May 83, Keith Petersen, W8SDZ
  74. ;    - fixed to allow assembly with ASM.COM
  75. ;    - fixed screen clear bug when crossing read boundries
  76. ;    - added strip for high-order bit in character before
  77. ;        printing (needed for WordStar files)
  78. ;    - improved stack routines
  79. ;    - fixed bug in console input routine
  80. ;    - removed Z80 dependant code (now works on 8080 too)
  81. ;
  82. ; Ver 1.02, 06 May 83, Lucien Pan, Toronto, Canada
  83. ;     - fixed some minor bugs
  84. ;     - returns to ccp w/o warm boot
  85. ;     - filters form-feeds (useful in .PRN files)
  86. ;     - scrolls foward/backwards by same number of lines
  87. ;     - disable/enable cursor during scroll for H-19
  88. ;
  89. ; Ver 1.01, 30 Mar 83 - added BDOS function  6.  W.F.Mcgee
  90. ;
  91. ; Ver 1.00, 23 Aug 82 Phil Cary, 748 Kenilworth Parkway, Baton
  92. ; Rouge, LA  70808
  93. ;
  94. ; BISHOW is a  buffered,  bidirectional  version  of  SHOW.ASM
  95. ; which first appeared in Interface Age, November, 1981.  That
  96. ; program  could  only  scroll  forward  in  a  file, and read
  97. ; sectors from disk one at a time as they  were  sent  to  the
  98. ; console.   I  used SHOW frequently to take a quick look at a
  99. ; file without loading a  big  text  editor,  and  to  examine
  100. ; another  file  with the RUN command while in Wordstar.  TYPE
  101. ; does not work since it is not a file that Wordstar can  load
  102. ; and run.
  103. ;
  104. ; This  bidirectional  version  uses  random access  reads. In
  105. ; addition, buffering was added so that  the  number  of  disk
  106. ; reads  would  be  reduced,  and  moving  back and forth in a
  107. ; moderate sized file would be speeded up.  There is  a  trade
  108. ; off between the size of the buffer and the length of time it
  109. ; takes to refill the buffer which should be set to the user's
  110. ; preference.
  111. ;
  112. ; There are several customizing items in this program.  One is 
  113. ; the equate "maxsec" which sets the buffer size.   Another is 
  114. ; the  string  in the subroutine "clrscr" just after  the  org 
  115. ; statement.   This should be changed to erase the screen  and 
  116. ; home  the cursor for the user's terminal.   The program,  as 
  117. ; written,  requires a terminal with an erase screen and  home 
  118. ; cursor  function.   Some  terminals  do not allow  the  80th 
  119. ; column  to be filled without going to the  next  line.   For 
  120. ; this reason, the screen width ("maxchr") initially is set to 
  121. ; 79.   The screen sizes can be changed using the "S" (screen) 
  122. ; command.  The parameters that can be changed are the maximum 
  123. ; column  displayed ("maxchr"),  the minimum column  displayed 
  124. ; (allowing  you  to "window" the output),  and the number  of 
  125. ; lines ("scroln").   A zero for the maximum column  displayed 
  126. ; will  give and unlimited screen width.   The maximum  column 
  127. ; displayed  and  the number of lines can be set when  calling 
  128. ; BISHOW,  e.g.,  "BISHOW file.nam 79 24" will give 79 columns 
  129. ; and 24 lines,  and "BISHOW file.nam 79" will give 79 columns 
  130. ; with the default number of lines.  The last customizing item 
  131. ; is the "short" equate.   If this is chosen, the multiplicity 
  132. ; of command forms is not allowed (see the beginning to change 
  133. ; the  commands  used),  and certain messages  are  shortened.  
  134. ; This will allow  BISHOW  to fit into a  1K area.  Direct I/O 
  135. ; to the console is used to avoid echoing the commands to  the 
  136. ; console as the CP/M write console function does.
  137. ;
  138. ; Just  a  small contribution to the public domain software as
  139. ; partial payment for the many fine and  educational  programs
  140. ; the system has given me.  Phil Cary.
  141. ;
  142. ;Define version number for help message
  143. ;
  144. VERS    EQU    3        ;Note current use in DB constrains VERS & 
  145. REVS    EQU    02        ; REVS to be one and two digits respectively
  146. ;
  147. FALSE    EQU    0
  148. TRUE    EQU    NOT FALSE
  149. ;
  150. ;    ASCII equates
  151. ;
  152. ENDMSG    EQU    0        ;null
  153. BS    EQU    8        ;Backspace
  154. TAB    EQU    9        ;tab
  155. LF    EQU    0AH        ;line feed
  156. FEED    EQU    0CH        ;form feed
  157. CR    EQU    0DH        ;carriage return
  158. EOF    EQU    1AH        ;end of file
  159. ESC    EQU    1BH        ;escape
  160. SPACE    EQU    20H        ;space
  161. ;
  162. ;------------------------------------------------------------------------------
  163. ; @@@@@
  164. ;    /////////////////////  User settings  ///////////////////////
  165. ;
  166. HEATH    EQU    FALSE        ;assemble for H-19 terminal
  167. OSBORNE    EQU    FALSE        ;assemble for 52-column screen
  168. ;
  169. SHORT    EQU    TRUE        ;no SQ or LBR = 1k / with SQ and LBR = 2k
  170. LONG    EQU    NOT SHORT    ;duplicate keys, includes help, margin set
  171.  
  172. SQUEEZE    EQU    TRUE        ;Optional, to handle squeezed files 
  173. LIBRARY    EQU    TRUE        ;Optional, to handle .LBR files
  174. ;
  175. NOWAIT    EQU    TRUE        ;true = no wait after screen clear 
  176. SILENT    EQU    TRUE        ;true = no superfluous "unsqueezing text" msg
  177. ;
  178.     IF     NOT OSBORNE
  179. SCROLN    EQU    24        ;number of lines per scroll
  180. MAXCHR    EQU    79        ;number of characters per line
  181.     ENDIF
  182. ;
  183.     IF    OSBORNE
  184. SCROLN    EQU    24        ;number of lines per scroll
  185. MAXCHR    EQU    51        ;number of characters per line
  186.     ENDIF
  187. ;
  188. ;     /////////  change the help tables if you change keys  //////////
  189. ;
  190. ;    command keys - short version
  191. ;
  192. LINE    EQU    'X'-40H
  193. LINE2    EQU     CR
  194. PAGE    EQU    'C'-40H
  195. PAGE2    EQU     SPACE
  196. LINEUP    EQU    'E'-40H
  197. LINEUP2    EQU    'P'
  198. PAGEUP    EQU    'R'-40H
  199. PAGEUP2    EQU    'B'
  200. ARWLFT    EQU    'S'-40H
  201. ARWLFT2 EQU    'H'-40H
  202. ARWRT    EQU    'D'-40H
  203. ARWRT2    EQU    TAB
  204. TOP    EQU    'T'
  205. TOP2    EQU    '1'
  206. QUIT    EQU    'Q'
  207. QUITCL    EQU    ESC
  208. ;
  209. ;    additional command keys - long version
  210. ;
  211.     IF    LONG
  212. LINE3    EQU    LF 
  213. LINE4    EQU    '+'
  214. LINE5    EQU    'Z'-40H
  215. LINE6    EQU    'N'
  216. PAGE3    EQU    'F'
  217. PAGE4    EQU    'F'-40H
  218. PAGE5    EQU    'V'-40H
  219. LINEUP3    EQU    'K'-40H
  220. LINEUP4    EQU    '-'
  221. LINEUP5    EQU    'W'-40H
  222. PAGEUP3    EQU    'B'-40H
  223. ARWLFT3 EQU    'A'-40H
  224. ARWRT3    EQU    'L'-40H
  225. SETKEY    EQU    'S'
  226. HUH    EQU    'H'
  227. HUH2    EQU    '?'
  228.     ENDIF
  229. ;
  230. ;    //////  check help and clrscr routines at @@@@@  below  ////////
  231. ;
  232. ;------------------------------------------------------------------------------
  233. ;
  234. BASE    EQU    0        ;standard zero base CP/M
  235. ;
  236. ;    BDOS functions
  237. ;
  238. CONOUT    EQU    2        ;console write
  239. OPEN    EQU    15        ;open file
  240. CLOSE    EQU    16        ;close file
  241. READR    EQU    33        ;read file random access
  242. STDMA    EQU    26        ;set dma address
  243. ;
  244. ;    Page zero equates
  245. ;
  246. WBOOT    EQU    BASE        ;warm boot entry point
  247. BDOS    EQU    WBOOT+5        ;BDOS entry point
  248. FCB    EQU    WBOOT+5CH    ;default fcb drive number
  249. CMDTAIL    EQU    WBOOT+80H    ;location of command tail
  250. FCBFN    EQU    FCB+1        ;start of filename
  251. FCBFT    EQU    FCB+9        ;start of filetype
  252. FCBEX    EQU    FCB+12        ;current extent number
  253. FCBCRR    EQU    FCB+33        ;current record number, random access
  254. TPA    EQU    WBOOT+100H    ;transient program area
  255. ;
  256. ;    Operational equates
  257. ;
  258. MAXSEC    EQU    32        ;number of sectors in buffer
  259. SQSIGN    EQU    0FF76H        ;Signature for SQ files
  260. LBSIGN    EQU    2000H        ;Signature for library files
  261. DLE    EQU    090H        ;Char flag for run compression (SQ)
  262. ;
  263.     ORG    TPA
  264. ;
  265.     JMP    START        ;skip over next subroutines
  266. ;
  267. ;------------------------------------------------------------------------------
  268. ; @@@@@
  269. ;    /////////  change help tables to reflect key changes  /////////
  270. ;
  271.     IF    LONG AND NOT OSBORNE
  272. HELP3:                
  273.     CALL    CDISP
  274.     DB    CR,LF,LF
  275.     DB    '   ^E        ^X       ^R        ^C       T    ^S    ^D  '
  276.     DB    '   S    H     Q',CR,LF
  277.     DB    'up line  next line  up page  next page  top  left  right'
  278.     DB    '  set  help  quit',CR,LF    
  279.     DB    '  P  -      cr +       B       F sp      1    bs    tab '
  280.     DB    '   S    ?    ESC',CR,LF
  281.     DB    ' ^W ^K    ^Z lf N     ^B      ^F ^V           ^A    ^L',CR,LF
  282.     DB    ENDMSG
  283.     JMP    GETCMD
  284.     ENDIF
  285. ;
  286.     IF    LONG AND OSBORNE
  287. HELP3:    JMP    HELP2
  288.     ENDIF
  289. ;
  290.     IF    LONG AND NOT OSBORNE
  291. HELP2:
  292.     CALL    CDISP
  293.     DB    CR,LF,LF
  294.     DB    '     P  ^E line up     B  ^R page up     bs  ^S left '
  295.     DB    '     S   set    Q   quit',CR,LF
  296.     DB    '     cr ^X line        sp ^C page        tab ^D right'
  297.     DB    '     T 1 top    ESC clear',CR,LF
  298.     DB    ENDMSG
  299.     JMP    GETCMD
  300.     ENDIF
  301. ;
  302.     IF    LONG AND OSBORNE
  303. HELP2:
  304.     CALL    CDISP
  305.     DB    CR,LF,LF
  306.     DB    '^E line up  ^R page up  ^S left    T top   Q  quit',CR,LF
  307.     DB    '^X line     ^C page     ^D right   S set  ESC clear',CR,LF
  308.     DB    ENDMSG
  309.     JMP    GETCMD
  310.     ENDIF
  311. ;
  312. ;    //////////////////  check your clear code  ///////////////////
  313. ;
  314. CLRSCR:        
  315.     CALL    CDISP        ;command to erase screen and home cursor
  316. ;
  317.     IF    NOT (HEATH OR OSBORNE)
  318.     DB    ESC,'+',ENDMSG    ;put your screen clear string here
  319.     ENDIF
  320. ;
  321.     IF    HEATH
  322.     DB    ESC,'E',ENDMSG    ;for H/Z-19 terminal -- Change as required
  323.     ENDIF
  324. ;
  325.     IF    OSBORNE
  326.     DB    1AH,ENDMSG    ;for Osborne (& Televideo?)
  327.     ENDIF
  328. ;
  329. ;    ///////////////////  end of user settings  ////////////////////
  330. ;
  331. ;------------------------------------------------------------------------------
  332. ;
  333.     IF    NOT NOWAIT
  334. WAIT:    MVI    B,0        ;waste time (may or may not be necessary)
  335. WAIT1:    XTHL            ;good time gobbeler!
  336.     XTHL
  337.     DCR    B
  338.     JNZ    WAIT1
  339.     ENDIF
  340. ;
  341.     RET            ;return from clrscr
  342. ;
  343. START:    
  344.     IF    HEATH
  345.     CALL    CDISP
  346.     DB    ESC,'x5',ENDMSG    ;disable cursor
  347.     ENDIF
  348. ;
  349.     LXI    H,0        ;get ccp's stack
  350.     DAD    SP
  351.     SHLD    STACK        ;save old stack for reinstatement at exit
  352.     LXI    SP,STACK    ;set new stack
  353.     LXI    H,CMDTAIL    ;point to command tail
  354.     MOV    B,M        ;get number of char in tail
  355.     INX    H        ;point to first character
  356.     INR    B
  357. ;
  358.     CALL    EATSP        ;Step to next non-bl in input
  359.     JZ    OPENF        ;no more characters
  360. ;
  361.     CALL    FILNAM        ;Skip file name, returns <B>=0 or <A>=20H
  362.     JZ    OPENF        ;only file name in tail
  363. ;
  364. ;            Check if there is a member name
  365.     CALL    EATSP        ;Step to next non-bl in input
  366.     JZ    OPENF        ;no more characters
  367.     CPI    '9'+1        ;Numeric?
  368. ;
  369.     IF    LIBRARY
  370.     JNC    MEMB        ;No -
  371.     ENDIF
  372. ;
  373.     CPI    '0'
  374.     JNC    NUMBER        ;Yes - must be width & height
  375. ;
  376. ;
  377.     IF    LIBRARY        ;Have member name (at FCB+11H)
  378. MEMB:
  379.     STA    MEMNAM        ;No - have member name
  380.     PUSH    H        ;Posn in command line 
  381.     PUSH    B        ;# of chars remaining
  382.     LXI    H,FCB+11H    ;Source
  383.     LXI    D,MEMFCB+1    ;Destination
  384.     MVI    B,11        ;Move name + type
  385.     CALL    MOVE 
  386. ;                add LBR suffix if required
  387.     LXI    H,FCB+9        ;Is there a suffix
  388.     MOV    A,M
  389.     CPI    SPACE
  390.     JNZ    NUMBR2        ;Yes - leave
  391.     MVI    M,'L'
  392.     INX    H
  393.     MVI    M,'B'
  394.     INX    H
  395.     MVI    M,'R'
  396. NUMBR2:
  397.     POP    B
  398.     POP    H
  399.     CALL    FILNAM        ;Skip member name, returns <B>=0 or <A>=20H
  400.     JZ    OPENF        ;end
  401.     ENDIF            ;above section included in library ver. only
  402. ;
  403. ;            Handle screen width & height
  404. NUMBER:
  405.     LXI    D,CHRMAX    ;point to chr/line
  406.     CALL    GETNBR        ;get number of characters/line
  407.     JC    HELP        ;invalid number
  408.     LXI    D,LINMAX    ;point to number of lines
  409.     CNZ    GETNBR        ;call only if characters still in
  410.                 ;__command tail
  411.     JC    HELP        ;invalid number
  412. ;
  413. OPENF:    CALL    OPNFIL        ;open file in default fcb
  414. ;
  415.     IF    SQUEEZE
  416.     CALL    CHKSQ        ;Check for squeezed, init if
  417.     ENDIF            ;Returns first word in file in <HL>
  418. ;
  419.     IF    LIBRARY
  420.     CALL    FILBF0        ;fill the disk buffer with start of file
  421.     CALL    CHKLB        ;Check for library file
  422.     CALL    CLRSCR
  423.     JMP    WRTFW0        ;Buffer contains top sectors
  424.     ENDIF    
  425. ;
  426. WRTFWD:
  427.     CALL    CLRSCR        ;erase the screen
  428.     CALL    FILBF0        ;fill the disk buffer with start of file
  429. WRTFW0:
  430.     LXI    H,DSKBUF    ;point to beginning of buffer
  431. ;
  432. WRTFW1:
  433.     MOV    A,M        ;get a character
  434.     CPI    EOF        ;see if eof
  435.     JZ    GETCMD        ;yes, wait for command
  436.     INX    H        ;bump pointer
  437.     ANI    7FH        ;strip high bit
  438.     CPI    FEED        ;filter form-feeds
  439.     JZ    FILTER        ;__commonly found in .PRN files
  440.     CALL    CO1        ;put it on console
  441.     CPI    CR        ;see if end of line
  442.     JZ    FWDCNT        ;yes, adjust line count
  443. ;
  444. WRTFW2:    LXI    D,ENDBUF    ;get end of buffer address
  445.     CALL    cmphlde        ;Is HL> gt DE> (end of buff)
  446. ;                ; Note test is LT now, not NE (v1.81)
  447.     JC    WRTFW1        ;continue with next character
  448.     CALL    FILBUF        ;fill the disk buffer with next sectors
  449.     JMP    WRTFW0        ;start over
  450. ;
  451. HELP:    CALL    CDISP
  452.     DB    CR,LF,'BISHOW '
  453.     DB    (VERS MOD 10)+'0','.'
  454.     DB    REVS/10+'0',(REVS MOD 10)+'0',CR,LF
  455. ;    
  456.     IF    LIBRARY AND SQUEEZE
  457.     DB    'bishow d:ANYsqFIL.lbr '
  458.     ENDIF
  459. ;
  460.     IF    LIBRARY AND NOT SQUEEZE
  461.     DB    'bishow a:FILnotSQ.lbr '
  462.     ENDIF
  463. ;
  464.     IF    SQUEEZE AND NOT LIBRARY
  465.     DB    'bishow a:SQZorNOT.fil '    
  466.         ENDIF
  467. ;    
  468.     IF     (NOT SQUEEZE) AND (NOT LIBRARY)
  469.     DB    'bishow d:anyPLAIN.fil ' 
  470.     ENDIF
  471. ;
  472.     IF    LIBRARY
  473.     DB    '[member] '
  474.     ENDIF
  475.     DB    '[cols [lines]]',CR,LF,ENDMSG
  476.     JMP    EXIT1
  477. ;
  478. FILTER:    PUSH    PSW        ;save status
  479.     MVI    A,'^'        ;print '^' in front
  480.     CALL    CO1        ;__of control character
  481.     POP    PSW        ;restore status
  482.     ADI    40H        ;mask into displayable char
  483.     CALL    CO1        ;display filtered control char
  484. ;
  485. FWDCNT:    LDA    LINCNT        ;get number of lines displayed
  486.     INR    A        ;bump it
  487.     STA    LINCNT        ;__and store it
  488.     MOV    D,A        ;save lincnt
  489.     LDA    LINMAX        ;get max number of line
  490.     CMP    D        ;compare with line count
  491.     JNZ    WRTFW2        ;if not there, continue, else get command
  492.     XRA    A        ;zero the
  493.     STA    LINCNT        ;__line count
  494. ;
  495. GETCMD:    PUSH    H
  496.     PUSH    D
  497.     PUSH    B
  498. ;
  499. GETCM1:    CALL    GETIN        ;Get input char if any
  500.     ORA    A        ;loop till char avail
  501.     JZ    GETCM1
  502.     POP    B
  503.     POP    D
  504.     POP    H
  505.     CPI    'a'        ;change command to
  506.     JC    GETCM2        ;__upper case
  507.     CPI    'z'+1
  508.     JNC    GETCM2
  509.     XRI    20H        ;is lower case, make upper case
  510. ;
  511. GETCM2:        
  512. ;    ///////////////  commands for short version  /////////////////
  513. ;
  514.     CPI    LINE        ;scroll next line
  515.     JZ    WRTNXT
  516.     CPI    LINE2
  517.     JZ    WRTNXT
  518.     CPI    PAGE        ;scroll next page
  519.     JZ    WRTFW1
  520.     CPI    PAGE2        
  521.     JZ    WRTFW1
  522.     CPI    LINEUP        ;scroll prev line
  523.     JZ    WRTPRV
  524.     CPI    LINEUP2
  525.     JZ    WRTPRV
  526.     CPI    PAGEUP        ;scroll page backward
  527.     JZ    WRTBAK
  528.     CPI    PAGEUP2
  529.     JZ    WRTBAK
  530.     CPI    ARWLFT        ;scroll left
  531.     JZ    ADJMM
  532.     CPI    ARWLFT2
  533.     JZ    ADJMM        
  534.     CPI    ARWRT        ;scroll right
  535.     JZ    ADJMM
  536.     CPI    ARWRT2
  537.     JZ    ADJMM
  538.     CPI    TOP        ;go to 1st line of file
  539.     JZ    WRTTOP
  540.     CPI    TOP2
  541.     JZ    WRTTOP
  542.     CPI    QUIT        ;does not clear screen
  543.     JZ    EXIT        
  544.     CPI    QUITCL        ;clears screen
  545.     JZ    EXITCL        
  546. ;
  547. ;    ////////////////  commands for long version  /////////////////
  548. ;
  549.     IF    LONG
  550. ;
  551.     CPI    LINE3
  552.     JZ    WRTNXT
  553.     CPI    LINE4
  554.     JZ    WRTNXT
  555.     CPI    LINE5
  556.     JZ    WRTNXT
  557.     CPI    LINE6
  558.     JZ    WRTNXT
  559. ;
  560.     CPI    PAGE3
  561.     JZ    WRTFW1
  562.     CPI    PAGE4
  563.     JZ    WRTFW1
  564.     CPI    PAGE5
  565.     JZ    WRTFW1
  566. ;
  567.     CPI    LINEUP3
  568.     JZ    WRTPRV
  569.     CPI    LINEUP4
  570.     JZ    WRTPRV
  571.     CPI    LINEUP5
  572.     JZ    WRTPRV
  573. ;
  574.     CPI    PAGEUP3
  575.     JZ    WRTBAK
  576. ;
  577.     CPI    ARWLFT3
  578.     JZ    ADJMM        
  579. ;
  580.     CPI    ARWRT3
  581.     JZ    ADJMM
  582. ;
  583.     CPI    SETKEY
  584.     JZ    SETSCR
  585. ;
  586.     CPI    HUH
  587.     JZ    HELP2        ;brief table of commands
  588.     CPI    HUH2
  589.     JZ    HELP3        ;full table of commands
  590. ;
  591.     ENDIF
  592. ;
  593.     JMP    GETCMD
  594. ;
  595. ;
  596. ;            Go to top of file
  597. WRTTOP:
  598.     LDA    TOPBUF        ;Get top in buffer flag
  599.     ORA    A
  600.     JNZ    WRTFWD        ;No - the hard way
  601.     CALL    CLRSCR        ;erase the screen
  602. WRTTO1:
  603.     XRA    A
  604.     STA    LINCNT        ;Clear lines put so far
  605.     JMP    WRTFW0        ;Buffer contains top sectors
  606. ;
  607. ;            Write one more line
  608. WRTNXT:    LDA    LINMAX
  609.     DCR    A        ;fool wrtfw1 to only write one line
  610.     STA    LINCNT
  611.     JMP    WRTFW1
  612. ;            Back up one line
  613. WRTPRV:    LDA    LINMAX        ;back up one screen + 1 line
  614.     INR    A
  615.     JMP    WRTBK0
  616. ;            Back up full screen
  617. WRTBAK:    LDA    LINMAX        ;get screen line count
  618.     ADD    A        ;__multiply by 2
  619. ;
  620. WRTBK0:    INR    A        ;__and add 1
  621.     STA    LINCNT        ;__to backup to previous page
  622.     CALL    CLRSCR        ;clear the screen
  623. ;
  624. WRTBK1:    LXI    D,DSKBUF    ;get address of start of buffer start
  625.     CALL    cmphlde        ;Is HL> LT DE> (start of buff)
  626. ;                ; Note test is LT now, not NE (v1.81)
  627.     JC    FILBAK        ;Go refill buffer
  628. ;
  629. WRTBK2:    MOV    A,M        ;get a character
  630.     ANI    7FH        ;strip high bit
  631.     DCX    H        ;decrement buffer
  632.     CPI    CR        ;see if end of line
  633.     JZ    BAKCNT        ;__or form-feed
  634.     CPI    FEED        ;__and adjust line count if so
  635.     JNZ    WRTBK1        ;else, loop if not
  636. ;
  637. BAKCNT:    LDA    LINCNT        ;else, get number of lines to move back
  638.     DCR    A        ;__and decrement it
  639.     STA    LINCNT        ;__store it
  640.     JNZ    WRTBK1        ;__and loop if not there
  641.     INX    H        ;else bump pointer
  642.     INX    H        ;__to account for dcx
  643.     JMP    WRTFW1        ;and go write a screen
  644. ;
  645. FILBAK:
  646. ;            Test for top of file
  647.     LDA    TOPBUF        ;Get top in buffer flag
  648.     ORA    A
  649.     JZ    WRTTO1        ;Yes - start of file in buffer
  650. ;            Start of file not in buffer, step back
  651.     LHLD    SECCNT        ;Get no of sectors last read
  652.     LXI    D,MAXSEC    ;get the buffer size
  653.     DAD    D        ;add them
  654.     XCHG            ;__and put them in DE
  655.     LDA    FCBCRR        ;subtract low order byte 
  656.     SUB    E        ;__from current record count
  657.     STA    FCBCRR        ;__and store in current record count
  658.     LDA    FCBCRR+1    ;same with high order byte
  659.     SBB    D        ;__but with borrow
  660.     JM    WRTFWD        ;if beyond beginning of file, start over
  661.     STA    FCBCRR+1    ;else, store high order byte
  662.     CALL    FILBUF        ;fill the buffer
  663.     LXI    H,ENDBUF    ;__and point to end of buffer
  664.     CALL    CLRSCR        ;clear the screen
  665.     JMP    WRTBK2        ;continue moving back in file
  666. ;
  667. ;            Fill buffer with top of file 
  668. FILBF0:
  669.     XRA    A        ;get a 0
  670.     STA    LINCNT        ;store in line count
  671.     STA    CHRCNT        ;store in character count
  672. ;                Do not reset the current extent!!!
  673. ;                BDOS will switch extents only if the no
  674. ;                specified ( <FCBEX> ) does NOT agree with
  675. ;                the wanted no <FCBCRR>. 
  676.     STA    FCBCRR        ;Reset to sector zero
  677. ;
  678.     IF    NOT LIBRARY
  679.     STA    FCBCRR+1    ;
  680.     STA    FCBCRR+2    ;__and clear the overflow
  681.     ENDIF
  682. ;
  683.     IF    LIBRARY
  684.     LHLD    SCZERO        ;Set to sector zero for file/member
  685.     SHLD    FCBCRR
  686.     ENDIF
  687. ;
  688. ;            ;Fill buffer from spec'd sector
  689. FILBUF:
  690.     MVI    B,MAXSEC    ;number of sectors to resd
  691. FILB1S:
  692. ;
  693.     IF    LIBRARY
  694.     LHLD    SCZERO        ;Get top sector for member
  695.     XCHG 
  696.     LHLD    FCBCRR        ;Is this top of file?
  697.     CALL    cmphlde        ;This it? (<A>=0 if equal)
  698.     ENDIF
  699. ;
  700.     IF    NOT LIBRARY    
  701.     LHLD    FCBCRR        ;Is this top of file?
  702.     MOV    A,H
  703.     ORA    L
  704.     ENDIF
  705. ;
  706.     STA    TOPBUF        ;Set top of file in buffer flag
  707.     LXI    D,DSKBUF    ;load start of disk buffer
  708.     LXI    H,0        ;zero out the
  709.     SHLD    SECCNT        ;__number of sectors in buffer
  710. ;                ; Z - top, NZ - not top 
  711.     IF    SQUEEZE
  712.     LDA    SQFLG        ;Is this a squeezed file
  713.     ORA    A
  714.     JNZ    FILSQ        ;Yes -
  715.     ENDIF
  716. ;
  717. FILBU1:
  718.     PUSH    H        ;save all
  719.     PUSH    D        ;__registers from
  720.     PUSH    B        ;__BDOS clobber
  721.     MVI     C,STDMA        ;set dma to
  722.     CALL    BDOS        ;__disk buffer
  723. ;
  724.     LXI    D,FCB        ;set up to read
  725.     MVI    C,READR        ;__a record
  726.     CALL    BDOS        ;do it
  727.     ORA    A        ;read OK?
  728.     LHLD    FCBCRR        ;get current record number
  729.     INX    H        ;__bump it
  730.     SHLD    FCBCRR        ;__and save it
  731.     LHLD    SECCNT        ;get sectors in buffer
  732.     INX    H        ;bump it
  733.     SHLD    SECCNT        ;store it
  734.     POP    B
  735.     POP    D
  736.     POP    H
  737.     JNZ    RDERR        ;no, last sector read
  738. ;
  739.     IF    LIBRARY
  740.     PUSH    D        ;Save sector buffer pointer
  741.     LHLD    FCBCRR        ;get current record number
  742.     XCHG
  743.     LHLD    SCLAST        ;& get last sector for member (or FFFF)
  744.     CALL    cmphlde        ;Are we within member 
  745.     POP    D
  746.     JC    RDERR        ;no, last sector read
  747.     ENDIF
  748. ;
  749.     DCR    B        ;decrement it
  750.     RZ            ;if done return
  751.     LXI    H,128        ;else, add 128 to
  752.     DAD    D        ;__dma address
  753.     XCHG            ;put it in de
  754.     JMP    FILBU1        ;read another sector
  755. ;
  756.     IF    SQUEEZE
  757. ;            Fill buffer from squeezed file
  758. ;            This rtn handles mapping from unsq sector #
  759. ;            to sector, byte & bit in sq stream
  760. ;            on input FCBCRR contains wanted sector no,
  761. ;            ( no allowance made for sectors # over 65535)
  762. ;            <B> contains no of sectors wanted
  763. ;            DE> buffer where sectors wanted,
  764. ;             ignored in this version, always full DSKBUF
  765. FILSQ:
  766.     LHLD    FCBCRR        ;Get # for 1st sector wanted
  767.     XCHG
  768.     PUSH    D        ;Save to restore after unsq
  769.     LHLD    NXTSEC        ; & 1st sector after buffered ones  
  770.     CALL    cmphlde        ;Consecutive?
  771.     JZ    USQNXT        ;Yes - fine
  772.     JNC    USQBAK        ;No - lower
  773. ;    Next sect after latest but not consec
  774.     CALL    CDISP
  775.     DB    CR,LF,'Disjoint sectors',CR,LF,0
  776.     JMP    EXIT        ;Should never happen
  777. USQBAK:            ;Going backward
  778.     ENDIF
  779. ;
  780.     IF    SQUEEZE AND LIBRARY
  781.     LHLD    SCZERO        ;Get 1st sector for member
  782.     CALL    cmphlde        ;All the way back to start?
  783.     ENDIF
  784. ;
  785.     IF    SQUEEZE AND NOT LIBRARY
  786.     MOV    A,D        ;All the way?
  787.     ORA    E
  788.     ENDIF
  789. ;
  790.     IF    SQUEEZE
  791.     JNZ    USQNO1        ;No - MUST be prev!!!
  792.     LXI    H,SQMAP+2+8    ;Yes - reset SQMAP index to #3
  793.     SHLD    SQMAP
  794. USQNO1:
  795.     LHLD    SQMAP        ;Get index into mapping table
  796.     LXI    D,-8        ;Step back from next, past current to prev
  797.     DAD    D
  798.     SHLD    SQMAP        ; & save updated index for next
  799.     MOV    E,M        ;Get SQ sector no
  800.     INX    H
  801.     MOV    D,M
  802.     INX    H
  803.     MOV    C,M        ;Get byte offset
  804.     INX    H
  805.     MOV    A,M        ; & bit offset
  806.     STA    bitlft
  807.     XRA    A
  808.     STA    rcnt        ;No runs in progress
  809. ;                (assumption)
  810.     STA    SQBYT+1        ;Set offset 1st data byte
  811.     MOV    A,C
  812.     STA    SQBYT        ;For now offset within sector only
  813.     LHLD    SQBSC1        ;Get no of first SQ sector now in buffer
  814.     XCHG            ;<HL> wanted 1st sector, <DE> actual 1st
  815.     CALL    cmphlde        ;Is 1st buffer sector low/equal 1st data sect?
  816.     JNC    USQ1OK        ;Yes - first wanted sector SQ in buffer
  817. ;                 Max header 1035 bytes + file name)
  818. ;            Force reload of SQ buffer
  819.     SHLD    NXTSQS        ;No - 1st data sector b/4 1st buffer sect
  820. ;                 (note is probab not sector 0
  821. ;                 because of header, eg decoding tree)
  822.     MVI    A,1        ;Set rewind with I/O
  823.     STA    SQREWD        ;Set rewind flag
  824. ;                 SQBYT contains offset of 1st data byte
  825.     XRA    A
  826.     STA    SQEOF        ;Reset end of file on SQ
  827. ;                Leave current extent alone. This is how
  828. ;                BDOS knows how to switch extents. It checks
  829. ;                if the current extent no agrees with
  830. ;                the wanted record.
  831.     STA    FCBCRR+2    ; & count overflow, should not be necessary
  832.     MOV    D,A
  833.     JMP    USQNX1        ;Go adj buffer pointer
  834. ;                (NOP since <DE>=0
  835. ;            ;SQ text still in buffer
  836. USQ1OK:
  837. ;                <DE> # of 1st sector in SQ buf
  838. ;                <HL> # of wanted SQ sector 
  839. ;                (Max 100H SQ sectors in buffer)
  840.     MOV    A,L
  841.     SUB    E
  842.     RAR            ;Convert to pages (100H)
  843. ;                 Know Cy=0 in
  844. ;                 leaves Cy if odd no of sects
  845.     MOV    D,A
  846.     MVI    A,0        ;Do not disturb Cy
  847.     RAR            ;Pu carry (now 80H or 00H) 
  848. USQNX1:
  849.     MOV    E,A
  850.     LHLD    SQBYT        ;Get offset of 1st data byte in wanted sect
  851.     DAD    D        ; --> offset in buffer
  852.     LXI    D,SQBUF
  853.     DAD    D        ;Convert to absolute addr
  854.     SHLD    inbufs        ;& set as next byte to unsqueeze
  855. ;
  856. USQNXT:            ;Next sector consecutive
  857.     LHLD    NXTSQS        ;Get no of next SQ sector 
  858. ;                (in case read reqd)
  859.     SHLD    FCBCRR
  860. ;            Build mapping table entry
  861.     LHLD    inbufs        ;Calc offset in buffer
  862.     LXI    D,-SQBUF
  863.     DAD    D
  864.     MOV    C,L        ;Keep offset within sector
  865.     LDA    bitlft        ;Get bit offset
  866.     MOV    B,A
  867.     ORA    A        ;On byte boundary?
  868.     MOV    A,C
  869.     JNZ    NOTBBY        ;No -
  870.     INR    A        ;Yes - no adj reqd
  871. NOTBBY:
  872.     ANI    7FH        ;Ensure sector relative
  873.     DAD    H        ;Convert to sector no
  874.     ORA    A        ;Is next byte at start of sect?
  875.     JNZ    SECTOK
  876.     DCR    H        ;Yes - step back one sector
  877. SECTOK:
  878.     DCR    A
  879.     ANI    7FH        ;& adj byte index
  880.     MOV    E,H
  881.     MVI    D,0
  882.     LHLD    SQBSC1        ;# of 1st sector in buffer
  883.     DAD    D
  884.     XCHG            ;<D> absolute SQ sector no
  885.     LHLD    SQMAP        ;Get index
  886.     MOV    M,E        ;Save abs SQ sector no
  887.     INX    H
  888.     MOV    M,D
  889.     INX    H
  890.     MOV    M,A        ;Save sector relative byte offset
  891.     INX    H
  892.     MOV    M,B        ;Save bitlft
  893.     INX    H
  894.     SHLD    SQMAP        ;Save new index
  895.     ENDIF
  896. ;
  897.     IF    SQUEEZE AND NOT SILENT
  898.     CALL    CDISP        ;Show msg where is
  899.     DB    '>>> Unsqueezing Text <<<',ENDMSG
  900.         ;Corrupts display if after CR but before LF
  901.     ENDIF
  902. ;
  903.     IF    SQUEEZE
  904.     CALL    FILUSQ        ;fills unsq buffer
  905.     ENDIF            ;SQEOF set as well then
  906. ;
  907.     IF    SQUEEZE AND NOT SILENT
  908.     CALL    CDISP        ;Remove msg just displayed, assumes
  909.                 ;BS works across start of line if reqd
  910.     DB    BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS
  911.     DB    BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS
  912.     DB    '                        '
  913.     DB    BS,BS,BS,BS,BS,BS,BS,BS    ,BS,BS,BS,BS
  914.     DB    BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,0
  915.     ENDIF
  916. ;
  917.     IF    SQUEEZE
  918.     LHLD    FCBCRR        ;Get no of next SQ sector
  919.     SHLD    NXTSQS
  920.     LHLD    nxtadr        ;Calc # of unsq sectors in buf
  921.     LXI    D,-DSKBUF    ;(as neg no)
  922.     DAD    D        ;Calc length
  923.     DAD    H        ; & convert to sectors in <H>
  924.     MOV    L,H
  925.     MVI    H,0
  926.     SHLD    SECCNT        ;Save # of sectors in DSKBUF
  927.     POP    D        ;Get FCBCRR as passed by calling rtn
  928.     DAD    D        ; & calc new one
  929.     SHLD    FCBCRR
  930.     SHLD    NXTSEC
  931.     RET
  932.     ENDIF
  933. ;
  934. ;
  935. ;We only get here if end of file
  936. ;
  937. RDERR:    MVI    A,EOF        ;get bogus eof
  938.     STAX    D        ;save at buffer end in case no eof in file
  939.     XRA    A        ;get a zero to direct to start of buffer
  940.     RET            ;__on ret
  941. ;
  942. OPNFIL:    LDA    FCBFN        ;point to first letter of filename
  943.     CPI    ' '        ;anything there?
  944.     JZ    HELP        ;no, give help message
  945.     XRA    A        ;get a 0
  946.     STA    FCBEX        ;zero current extent
  947.                 ;MUST open file on extent zero
  948.     LXI    D,FCB        ;file name in default fcb
  949.     MVI    C,OPEN        ;set up to open
  950.     CALL    BDOS        ;do it
  951.     INR    A        ;open OK?
  952.     RNZ            ;yes
  953.     CALL    CDISP        ;else, give error msg and quit
  954.     DB    'No File',ENDMSG
  955.     JMP    EXIT1        ;leave msg on screen on exit
  956. ;
  957. GETNBR:    MOV    A,M        ;get first digit
  958.     INX    H
  959.     DCR    B        ;b=number of characters left in buffer
  960.     RZ            ;no digit
  961.     CPI    SPACE
  962.     JZ    GETNBR        ;wait until next non-space
  963.     PUSH    D        ;save location to save number
  964.     MVI    D,0        ;initialize number
  965. ;
  966. GNUM1:    SUI    30H        ;change ASCII to number
  967.     JC    INVNUM        ;not a number
  968.     CPI    10
  969.     CMC
  970.     JC    INVNUM        ;not a number
  971.     PUSH    PSW        ;save number
  972.     MOV    A,D        ;multiply old number by 10
  973.     ADD    A        ;*2
  974.     ADD    A        ;*4
  975.     ADD    A        ;*8
  976.     ADD    D        ;*9
  977.     ADD    D        ;*10
  978.     MOV    D,A
  979.     POP    PSW        ;restore new digit
  980.     ADD    D
  981.     MOV    D,A
  982.     MOV    A,M        ;get next digit
  983.     INX    H
  984.     DCR    B
  985.     JZ    ENDNUM        ;end of number
  986.     CPI    SPACE
  987.     JNZ    GNUM1
  988. ;
  989. ENDNUM:    MOV    A,D        ;save number
  990.     DCR    A        ;correct number for co routines
  991.     XCHG            ;set to restore save location
  992.     POP    H        ;restore save location
  993.     MOV    M,A        ;save digit
  994.     XCHG            ;put buffer location where it belongs
  995.     MOV    A,B        ;see if any characters left in buffer
  996.     ORA    A        ;zero if no characters in buffer
  997.     RET
  998. ;
  999. INVNUM:    POP    D        ;correct stack
  1000.     RET
  1001. ;
  1002.     IF LONG
  1003. ASCIIN:    MVI    B,100        ;divide by 100, then change
  1004.     CALL    DIVIDE        ;__digit to ASCII and store at hl
  1005.     MVI    B,10        ;divide by 10, then change
  1006.     CALL    DIVIDE        ;__digit to ASCII and store at hl+1
  1007.     MVI    B,30H        ;change ones place number
  1008.     ADD    B        ;__to ASCII and store at hl+2
  1009.     MOV    M,A
  1010.     DCX    H        ;delete leading zeroes
  1011.     DCX    H        ;__in the number
  1012.     MVI    C,SPACE        ;__and replace with spaces
  1013.     MOV    A,B
  1014.     CMP    M        ;check first digit for '0'
  1015.     JNZ    CDISP        ;not zero
  1016.     MOV    M,C        ;replace with space
  1017.     INX    H
  1018.     CMP    M        ;check second digit for '0'
  1019.     JNZ    CDISP        ;not zero
  1020.     MOV    M,C        ;replace with space
  1021.     ENDIF
  1022. ;
  1023. CDISP:    XTHL            ;exchange top of stack and HL
  1024. ;
  1025. CDIS1:    MOV    A,M        ;HL now pointing to db message
  1026.     ORA    A        ;see if 0 at end of message
  1027.     INX    H
  1028.     JZ    CDIS2        ;yes, restore stack and return
  1029.     CALL    CO        ;no, print the character
  1030.     JMP    CDIS1        ;__and loop
  1031. ;
  1032. CDIS2:    XTHL            ;get return address on top of stack
  1033.     RET            ;__and return
  1034. ;
  1035. CO:    PUSH    B        ;Save the registers
  1036.     PUSH    D        ;__from bdos
  1037.     PUSH    H        ;__clobber
  1038. CO2:    PUSH    PSW
  1039.     MOV    E,A        ;set up character
  1040.     MVI    C,CONOUT    ;__to send to console
  1041.     CALL    BDOS        ;do it
  1042.     POP    PSW
  1043. CO5:    POP    H        ;restore
  1044.     POP    D        ;__the registers
  1045.     POP    B
  1046.     RET
  1047. ;
  1048. CO1:    PUSH    B        ;Save the registers
  1049.     PUSH    D
  1050.     PUSH    H
  1051.     MOV    E,A
  1052.     LXI    H,CHRCNT    ;Get address of character count
  1053.     CPI    CR        ;see if end of line
  1054.     JZ    ENDLIN        ;update line information
  1055.     CPI    LF        ;ignore linefeed
  1056.     JZ    CO2
  1057.     LDA    CHRMAX        ;get maximum characters per line
  1058.     CMP    M        ;see if too many char
  1059.     JC    CO5        ;don't print character
  1060.     MOV    A,E        ;restore and print character
  1061.     CPI    TAB        ;fix chrcnt for tabs
  1062.     JZ    TABFIX
  1063.     INR    M        ;increment character count
  1064.     LDA    CHRMIN        ;see if up to minimum display yet
  1065.     CMP    M
  1066.     MOV    A,E        ;restore character
  1067.     JNC    CO5        ;do not display character
  1068.     JMP    CO2        ;finally, display character
  1069. ;
  1070. ENDLIN:    MVI    M,0        ;reset character count
  1071.     JMP    CO2        ;print cr
  1072. ;
  1073. TABFIX:    MVI    A,08H        ;fix chrcnt for tabs
  1074.     ADD    M        ;increment to next 8-count
  1075.     ANI    0F8H        ;make into multiple of 8
  1076. ;
  1077. TAB2:    SUB    M        ;get number of space to go
  1078.     MOV    B,A
  1079. ;
  1080. TAB1:    MVI    A,SPACE        ;expand tab
  1081.     CALL    CO1
  1082.     DCR    B
  1083.     JNZ    TAB1        ;still more spaces
  1084.     JMP    CO5        ;exit routine
  1085. ;
  1086. ;
  1087.     IF    LONG
  1088. SETSCR:    PUSH    H
  1089.     PUSH    D
  1090.     PUSH    B
  1091. ;
  1092. GETMAX:    LDA    CHRMAX        ;get maximum number of characters
  1093.     INR    A
  1094.     LXI    H,HUNS
  1095.     CALL    ASCIIN        ;put ASCII number in message        
  1096.     DB    CR,LF,'Max Column: '
  1097. ;
  1098. HUNS:    DB    30H
  1099.     DB    30H
  1100.     DB    30H
  1101.     DB    ' New? ',ENDMSG
  1102.     CALL    GETINP        ;read input from console
  1103.     LXI    D,CHRMAX    ;set new chrmax in memory
  1104.     CALL    GETNBR
  1105.     JC    GETMAX        ;if error, repeat last message
  1106. ;
  1107. GETMIN:    LDA    CHRMIN        ;get minimum character display
  1108.     INR    A
  1109.     LXI    H,HUN
  1110.     CALL    ASCIIN        ;put ASCII number in message        
  1111.     DB    LF,'Min Column: '
  1112. ;
  1113. HUN:    DB    30H
  1114.     DB    30H
  1115.     DB    30H
  1116.     DB    ' New? ',ENDMSG
  1117.     CALL    GETINP        ;read input from console
  1118.     LXI    D,CHRMIN    ;set new chrmax in memory
  1119.     CALL    GETNBR
  1120.     JC    GETMIN        ;if error, repeat last message
  1121. ;
  1122. GETLIN:    LDA    LINMAX        ;get number of lines per display
  1123.     LXI    H,HUND
  1124.     CALL    ASCIIN        ;put ASCII number in message        
  1125.     DB    LF,'Lines per Page: '
  1126. ;
  1127. HUND:    DB    30H
  1128.     DB    30H
  1129.     DB    30H
  1130.     DB    ' New? ',ENDMSG
  1131.     CALL    GETINP        ;read input from console
  1132.     LXI    D,LINMAX    ;set new chrmax in memory
  1133.     CALL    GETNBR
  1134.     JC    GETLIN        ;if error, repeat last message
  1135.      POP    B
  1136.     POP    D
  1137.     POP    H
  1138. ;
  1139. WRTSAM:    LDA    LINMAX        ;write the same screen
  1140.     JMP    WRTBK0
  1141. ;
  1142. GETINP:    MVI    A,5        ;get set to read new maximum column
  1143.     STA    CMDTAIL
  1144.     MVI    C,0AH
  1145.     LXI    D,CMDTAIL
  1146.     CALL    BDOS        ;get maximum column
  1147.     LXI    H,CMDTAIL+1    ;now, change to ASCII
  1148.     MOV    B,M
  1149.     INX    H
  1150.     INR    B
  1151.     RET            ;return with input in buffer
  1152. ;
  1153.     ENDIF    ;above code (flying set) only if long
  1154. ;
  1155. ADJMM:                ;Adjust char min/max on cursor left/rt
  1156.     PUSH    H
  1157.     CPI    ARWLFT        ;Move left (decrease)?
  1158.     JZ    ADJM1        ; set flag
  1159.     CPI    ARWLFT2
  1160.     JZ    ADJM1
  1161. ;
  1162.     IF LONG
  1163.     CPI    ARWLFT3
  1164.     JZ    ADJM1
  1165.     ENDIF
  1166. ;
  1167. ADJM1:    LDA    CHRMAX        ;rightmost char to display
  1168.     MOV    H,A
  1169.     LDA    CHRMIN        ;leftmost char to display
  1170.     MVI    L,8        ;Scroll by 8
  1171.     JZ    ADJMMD        ;OK - adjust to left
  1172.     ADD    L        ;No - increase min, no limit
  1173.     PUSH    PSW
  1174.     MOV    A,L
  1175.     ADD    H        ;increase  max
  1176.     JMP    ADJMMS        ;OK - adjust to right
  1177. ADJMMD:
  1178.     SUB    L        ;adjust to left
  1179.     PUSH    PSW
  1180.     MOV    A,H
  1181.     SUB    L
  1182. ADJMMS:                ;adjust to right
  1183.     MOV    H,A        ;<H> max
  1184.     POP    PSW        ;<A> min
  1185.     CMP    H        ;Wrap, (max< min)
  1186.     JNC    ADJMMX        ;OK - leave unchanged
  1187.     STA    CHRMIN
  1188.     MOV    A,H
  1189.     STA    CHRMAX
  1190. ADJMMX:
  1191.     POP    H
  1192.     LDA    LINMAX        ;write the same screen
  1193.     JMP    WRTBK0        ;same effect as WRTSAM above
  1194. ;
  1195.     IF LONG
  1196. DIVIDE:    MVI    C,'0'-1        ;extract dividend of a div c
  1197. ;
  1198. DIV1:    INR    C        ;__and store in location pointed
  1199.     SUB    B        ;__to by hl
  1200.     JNC    DIV1
  1201.     ADD    B
  1202.     MOV    M,C        ;save ASCII digit
  1203.     INX    H        ;bump pointer to next location
  1204.     RET
  1205. ;
  1206.     ENDIF
  1207. ;
  1208. EXITCL:
  1209. ;            Clear screen only on <ESC> exit
  1210.     CALL    CLRSCR        ;clear the screen
  1211. ;
  1212. EXIT:
  1213. ;    CALL    GETIN        ;__get any waiting character
  1214. ;    CALL    GETIN        ;and a possible second character
  1215. ;
  1216.     IF    HEATH
  1217.     CALL    CDISP        ;re-enable cursor
  1218.     DB    ESC,'y5',ENDMSG
  1219.     ENDIF
  1220. ;
  1221.     LXI    D,FCB        ;close file
  1222.     MVI    C,CLOSE        ;--in case this is MP/M
  1223.     CALL    BDOS
  1224. ;
  1225. EXIT1:
  1226.     LHLD    STACK        ;get old stack
  1227.     SPHL
  1228.     RET            ;return to CCP
  1229. ;
  1230. ;
  1231.     IF    LIBRARY
  1232. CHKLB:                ;Check for Library file
  1233.     xra    a
  1234.     sta    memfcb
  1235.     sta    lbflg        ;Clear library flag
  1236.     LHLD    DSKBUF        ;Get 1st word in file
  1237.     lxi    d,lbsign    ;Get expected value
  1238.     call    cmphlde
  1239.     jz    islb
  1240. ;            Not library
  1241. ;
  1242.     lda    memnam        ;Was member specified
  1243.     ora    a
  1244.     rz            ;No - ok
  1245.     call    CDISP
  1246.     db    cr,lf,'Not LBR',cr,lf,0
  1247.     jmp    EXIT        ;Get out to leave msg visible
  1248. ;
  1249. ;            Is library
  1250. islb:
  1251.     mvi    a,1
  1252.     sta    LBFLG        ;Yes - set library flag
  1253.     LXI    H,DSKBUF+14    ;Set to dir size (in sectors)
  1254.     mov    a,m        ;Assume <255 entries
  1255.     RAL
  1256.     RAL            ;Convert # sectors to # entries
  1257.     DCR    A        ;Less 1 for file descriptor
  1258.     sta    dirsiz        ;directory size in entries
  1259.     mov    b,a        ;Save no of entries for loop
  1260.     LXI    H,DSKBUF+20H    ;Set 1st member entry
  1261.  
  1262.     CALL    CDISP        ;write a blank line before first dir line
  1263.     DB    CR,LF,0
  1264. ;
  1265. ;            Loop through directory entries
  1266. dirlp:
  1267.     push    b        ;Save no of entries remaining
  1268.     MOV    A,M        ;Get entry status
  1269.     ORA    A        ;Deleted?
  1270.     JNZ    nyet        ;Yes - skp to next
  1271.     LDA    MEMNAM        ;Do we have member name on command line?
  1272.     ORA    A
  1273.     JZ    DISPM        ;No - display member name routine
  1274. ;
  1275. ;        See if this is the requested member
  1276. ;
  1277.     mvi    b,12        ;Length of names + 00H in front
  1278.     lxi    d,memfcb
  1279.     call    cpstr        ;Compare names
  1280.     jz    found
  1281.     jmp    nyet
  1282. ;
  1283. ;        Display rather than look for the member
  1284. ;
  1285. DISPM:    mvi    b,11        ;Length of names
  1286.     push    h
  1287.     inx    h        ;Step to actual name
  1288. DSPMLP:
  1289.     mov    a,m
  1290.     call    CO        ;Display one char
  1291.     inx    h
  1292.     dcr    b        ;Reduce count remaining
  1293.     jz    nmend        ;end of name
  1294. ;
  1295.     ENDIF
  1296. ;
  1297.     IF    LIBRARY AND NOT OSBORNE
  1298. ;                (Bypass for Ozzys narrow screen)
  1299.     mov    a,b
  1300.     cpi    3        ;only 3 more?
  1301.     jnz    DSPMLP        ;No -
  1302.     mvi    a,'.'        ;Yes - put out dot
  1303.     call    CO
  1304. ;
  1305.     ENDIF
  1306. ;
  1307.     IF    LIBRARY 
  1308.     jmp    DSPMLP        ;Go for next char
  1309. ;
  1310.         ;Have now displayed member name
  1311. nmend:
  1312. ;                In later versions multiple across
  1313.     lxi    h,namexc    ;Max no of names across sofar
  1314.     mov    a,m
  1315.     inx    h        ;Step to names across sofar
  1316.     inr    m        ;Count current
  1317.     cmp    m        ;Over max?
  1318.     jnc    notmax        ;not yet
  1319.     mvi    m,0        ;Yes - reset
  1320.     call    CDISP
  1321.     DB    CR,LF,0
  1322.     jmp    nyet1
  1323. notmax:
  1324.     call    CDISP
  1325.     ENDIF
  1326.  
  1327.     IF    LIBRARY AND NOT OSBORNE
  1328.     DB    ' '
  1329.     ENDIF
  1330.  
  1331.     IF    LIBRARY
  1332.     DB    '| ',0
  1333. nyet1:
  1334.     POP    H        ;Reset to start of this entry
  1335. ;            
  1336. nyet:
  1337.     lxi    b,20h        ;Length of each entry
  1338.     dad    b        ;Step to next
  1339.     pop    b        ;Get entry count (remaining)
  1340.     dcr    b
  1341.     jnz    dirlp        ;More members
  1342.     LDA    MEMNAM        ;Do we have member name on command line?
  1343.     ORA    A
  1344.     JZ    EXIT        ;if not, we have shown dir, now exit
  1345.     call    CDISP
  1346.     db    'Not in LBR',cr,lf,0
  1347.     jmp    EXIT        ;and show the poor schmuck the directory
  1348. ;
  1349. ;            Found the member name
  1350. found:
  1351.     pop    b        ;Clear stack
  1352.     lxi    d,12
  1353.     dad    d
  1354.     push    h        ;save pointer for now,
  1355.     inx    h        ;point to size
  1356.     inx    h
  1357.     mov    a,m        ;get low byte
  1358.     inx    h
  1359.     mov    h,m
  1360.     mov    l,a
  1361.     ora    h        ;if a=0 then file is 0k
  1362.     jz    nullen        ;go complain
  1363.     xthl            ;get pointer back, save size
  1364.     mov    a,m        ;get file address
  1365.     inx    h
  1366.     mov    h,m
  1367.     mov    l,a
  1368.     SHLD    SCZERO        ;Save as first file sector
  1369.     POP    D        ; & get size back
  1370.     DAD    D        ;Convert to last sector no (inclusive)
  1371.     SHLD    SCLAST
  1372.     ENDIF
  1373. ;
  1374.     IF    LIBRARY AND SQUEEZE
  1375.     LDA    SQFLG        ;Get SQ flag in case of double squeeze
  1376.     ORA    A
  1377.     JZ    NOLBSQ        ;Ok, library itself not squeezed
  1378.     CALL    CDISP
  1379.     DB    'unSQ LBR',CR,LF,0
  1380.     JMP    EXIT
  1381. NOLBSQ:
  1382.     CALL    CHKSQ        ;Check if  member squeezed
  1383.     ENDIF
  1384. ;
  1385.     IF    LIBRARY
  1386.     CALL    FILBF0        ;Refill buffer, now for member
  1387. ;                 (FILBUF handles member offset in library)
  1388.     ret
  1389. ;
  1390. ;            ;Member is empty
  1391. nullen:
  1392.     CALL    CDISP
  1393.     DB    'Empty',CR,LF,0
  1394.     JMP    EXIT
  1395.     ENDIF
  1396. ;
  1397. ;            Get input if any
  1398. GETIN:
  1399.     MVI    C,6        ;direct console I/O
  1400.     MVI    E,0FFH        ;__set up for input
  1401.     CALL    BDOS        ;Get char
  1402.     RET
  1403. ;
  1404. ;            Compare strings HL> to DE> over <B> 
  1405. ;            <DE> and <B> are changed, <HL> kept     
  1406. cpstr:
  1407.     push    h
  1408. cp$lp:
  1409.     ldax    d
  1410.     cmp    m
  1411.     jnz    cp$ex        ;No match
  1412.     inx    d
  1413.     inx    h
  1414.     dcr    b
  1415.     jnz    cp$lp
  1416. cp$ex:
  1417.     pop    h
  1418.     ret
  1419. ;
  1420. ;            Compare <HL> to <DE>
  1421. ;             Z - equal; C - <HL> less than <DE> 
  1422. ;             if equal returns <A>=0
  1423. cmphlde:
  1424.     mov    a,h
  1425.     sub    d
  1426.     rnz
  1427.     mov    a,l
  1428.     sub    e
  1429.     ret
  1430. ;
  1431. ;            Skip blanks in input
  1432. ;
  1433. EATSP:    MOV    A,M        ;get character if there is one
  1434.     INX    H
  1435.     DCR    B        ;b=number of characters left
  1436.     RZ            ;no more characters
  1437.     CPI    SPACE        ;ignore spaces
  1438.     JZ    EATSP
  1439.     DCX    H        ;Step back to 1st non-blank
  1440.     INR    B
  1441.     ORA    A        ;Force NZ
  1442.     RET
  1443. ;
  1444. ;            Skip name in input
  1445. ;
  1446. FILNAM:    MOV    A,M        ;get characters in file name
  1447.     INX    H
  1448.     DCR    B        ;b=number of characters left
  1449.     RZ            ;only file name in tail
  1450.     CPI    SPACE        ;wait for next space
  1451.     JNZ    FILNAM
  1452.     ORA    A        ;Force NZ
  1453.     RET            ;Blank
  1454. ;
  1455. ;            Move from HL> to DE> over <B>
  1456. ;
  1457. MOVE:
  1458.     MOV    A,M
  1459.     STAX    D
  1460.     INX    H        ;Step to next source
  1461.     INX    D        ; & destination
  1462.     DCR    B        ;Reduce count (00=256)
  1463.     JNZ    MOVE
  1464.     RET
  1465. ;
  1466. ;
  1467.     IF    SQUEEZE
  1468. *******************************************************
  1469. * USQ support code                      *
  1470. * 10/12/83 by Dave Rand                      *
  1471. *******************************************************
  1472. ;
  1473. ;            Check for SQ file, init tree if so
  1474. CHKSQ:
  1475. ;            Initialize
  1476.     xra    a
  1477.     mov    l,a
  1478.     mov    h,l        ;clear <hl>
  1479.     STA    SQFLG        ;Make sure not set as squeezed yet 
  1480.     sta    SQEOF        ; end of file on SQ
  1481.     sta    SQREWD        ;Clear "rewinding" SQ file 
  1482.     sta    bitlft        ;force init char read
  1483.     sta    rcnt        ;and zero repeats
  1484.     sta    FCBCRR+2    ; and overflow
  1485.     shld    numvals        ;Clear # nodes
  1486.     ENDIF
  1487. ;
  1488.     IF    SQUEEZE AND LIBRARY
  1489.     LHLD    SCZERO        ;Get 1st sector for member
  1490.     SHLD    NXTSEC        ;& save as next sector
  1491.     ENDIF
  1492. ;
  1493.     IF    SQUEEZE
  1494.     shld    FCBCRR        ;Clear next record
  1495.     lxi    h,SQBUF        ;Set to input (squeezed) buffer 
  1496.     shld    inbufs
  1497.     shld    inbufu
  1498.     lxi    d,128
  1499.     dad    d
  1500.     shld    SQBUFE        ;Force exit on full buff aft 1 sect
  1501. ;                 causes the SQ buffer to contain
  1502. ;                 sectors 1+ only (not zero),
  1503. ;                 normally fine since sector 0 contains only
  1504. ;                 header info. Sector 0 will be reread
  1505. ;                 if contains data and needed  
  1506. ;        Read and validate signature word
  1507.     call    getw        ;Read  1st word in file
  1508.     lxi    d,sqsign    ;Get expected value
  1509.     call    cmphlde
  1510.     rnz
  1511.     mvi    a,1
  1512.     STA    SQFLG        ;Yes - set flag
  1513.     lhld    0006        ;Get top of memory
  1514.     lxi    d,sqbuf+100H*128 ;Limit buffer to max 100H
  1515.     call    cmphlde        ; sectors (FILBUF uses 8 bit count <B>)
  1516.     JC    toplow        ;use top
  1517.     xchg            ;use limit 
  1518. toplow:
  1519.     shld    SQBUFE        ;& store as full address 
  1520.     call    namlp        ;Skip past name
  1521.     call    usqtbl        ;Validate & load decoding tree
  1522.     jz    oak        ;tree ok
  1523.     call    CDISP
  1524.     db    cr,lf,'Bad SQ tree',cr,lf,0
  1525.     jmp    EXIT
  1526. oak:
  1527.     lxi    h,SQMAP+2    ;Point to 1st entry 
  1528.     shld    SQMAP        ;Set to 1at entry in SQ mapper
  1529.     ret
  1530. ;
  1531. ;            Read & save checksum
  1532. rdchks:
  1533.     call    getw        ;get cksum, and store
  1534.     shld    filchks
  1535.     ret
  1536. ;            Read & skip name
  1537. namlp:    call    getc        ;Loop to skip name
  1538.     jnz    erext        ;I/O error or unexpected EOF
  1539.     ora    a
  1540.     jnz    namlp        ;Not yet end of name
  1541.     ret
  1542. ;
  1543. ;            Load decoding tree
  1544. ;            This version uses 1 byte abslute node indices
  1545. ;            (1-ffH) and is thus limited to 255 nodes and 255
  1546. ;            characters represented in the squeezed file.
  1547. ;            (All different characters present in the original
  1548. ;            file as well as any added through run encoding.
  1549. ;            Runs of 3 or more consecutive identical characters
  1550. ;            are encoded as char, DLE, count, where count
  1551. ;            is a one byte field 00 - FFH) 
  1552. ;
  1553. usqtbl:
  1554.      call    getw        ;Get no of nodes
  1555.     mov    a,h
  1556.     ora    l
  1557.     jz    nzexit        ;Null tree
  1558.     shld    numvals
  1559.     mov    a,h        ;Max 257, 256 char & spec eof
  1560. ;                in this version allow for only 256
  1561. ;                diff codes, every ASCII and non-ASCII
  1562. ;                char would have to be present, or
  1563. ;                run repeat counts 128-255 (every one)
  1564.     ora    a        ;H/o byte should be zero
  1565.     jnz    nzexit
  1566.     lxi    d,SQTREE    ;Set to decoding tree
  1567. nodelp:    shld    nxtadr        ;Save no of nodes
  1568.     mov    a,h
  1569.     ora    l
  1570.     rz            ;Done all nodes
  1571.     call    cvnode        ;get node, falg byte in <H>,
  1572. ;                 index/char in <L>
  1573.     push    h
  1574.     call    cvnode        ;get second child/char
  1575.     pop    b
  1576.     mov    a,b
  1577.     ral            ;Shift flags to 8, 4 posns 
  1578.     ora    h        ;Combine in 1st child flags 
  1579.     xchg            ;HL> SQTREE, <A>,<C>,<E> node 
  1580.     mov    m,a        ;Store flags in table
  1581.     inx    h
  1582.     mov    m,c
  1583.     inx    h
  1584.     mov    m,e
  1585.     inx    h
  1586.     xchg            ;DE> SQTREE
  1587.     lhld    nxtadr        ;Nodes remaining
  1588.     dcx    h
  1589.     jmp    nodelp
  1590. ;            Get encoded node
  1591. ;            Our nodes contain 3 bytes:
  1592. ;            - flag byte,
  1593. ;            - left child index/char
  1594. ;            - right child index/char
  1595. ;            Nodes on input are 4 bytes,
  1596. ;            with each half containing
  1597. ;            an index (1-100h) or character,
  1598. ;            where characters are encoded as
  1599. ;            negative values -(char+1)
  1600. ;            Eof is encoded as -(100h+1)
  1601. cvnode:
  1602.     push    d
  1603.     call    getw        ;Get word, chld ptr or char
  1604.     pop    d
  1605.     mov    a,h
  1606.     ora    a
  1607.     rz            ;Child index, <H>=0,<L>=index
  1608.     mov    a,l
  1609.     cma
  1610.     mov    l,a        ;convert char to reg form
  1611.     mov    a,h        ;get h/o byte again
  1612.     cma
  1613.     inr    a        ;Conv to 1 if char, 2 if EOF
  1614.     mov    h,a
  1615.     cpi    1        ;Was that reg char?
  1616.     rz            ;Yes - complete
  1617.     adi    3        ;No convert EOF flag to 0100
  1618.     mov    h,a
  1619.     ret
  1620.  
  1621. ;            Exit with NZ flag
  1622. nzexit:
  1623.     mvi    a,2        ;tree error
  1624.     ora    a        ;Set NZ flag
  1625.     ret
  1626. ;
  1627. ;            Fill output buffer (unsqueezed char)
  1628. ;
  1629. FILUSQ:
  1630.     lda    SQREWD        ;Rewinding SQ input?
  1631.     ora    a
  1632.     jz    norewd        ;No
  1633. ;            Reload SQ buffer
  1634.     lhld    inbufs
  1635.     push    h        ;getrf resets
  1636.     call    getrf        ;Yes - reload buffer & get 1st 8 bits
  1637.     pop    h
  1638.     shld    inbufs        ;Set to first data byte to use
  1639. badj:
  1640.     mov    c,a
  1641.     lda    bitlft        ;Get preset 1st wanted bit no
  1642.     mov    c,a
  1643.     mvi    a,8
  1644.     sub    b        ; Calc adjmt reqd  
  1645. badjlp:
  1646.     dcr    a
  1647.     jz    badjfn        ; bit adjust finished
  1648.     mov    b,a
  1649.     mov    a,c
  1650.     rrc
  1651.     mov    c,a
  1652.     mov    a,b
  1653.     jmp    badjlp
  1654. badjfn:
  1655.     sta    bitbuf
  1656.     xra    a
  1657.     sta    SQREWD        ; & clear rewind flag
  1658. norewd:
  1659.     lxi    h,DSKBUF    ;reset buffer pointer
  1660.     xra    a
  1661. buflp:
  1662.     shld    nxtadr        ;Save as next byte in buffer
  1663.     rnz            ;End of file (NZ flag)
  1664. ;                 as set by GETNXT rtn below
  1665.     lxi    d,SQTREE    ;Get end of input
  1666.     call    cmphlde        ;buffer full (de < hl - not full)
  1667.     jnc    full        ;buffer is full
  1668.     call    getnxt        ;Get next decoded char
  1669.                 ;No checksum taken
  1670.     lhld    nxtadr        ;Next out buffer posn
  1671.     mov    m,a        ;Store char returned, may be EOF char
  1672.     inx    h
  1673.     jmp    buflp
  1674. ;
  1675. full:
  1676.     xra    a        ;Ensure Z
  1677.     ret            ;Return on full buffer
  1678. ;
  1679. ;
  1680. ;            Get next decoded character
  1681. ;
  1682. getnxt:    lda    rcnt        ;see if in the middle of
  1683.     ora    a        ;repeat sequence...
  1684.     jz    norpt
  1685.     dcr    a        ;Yes - reduce repeat remaining 
  1686.     sta    rcnt
  1687.     lda    last        ;Get latest char again
  1688.     cmp    a
  1689.     ret            ;Return with Z for ok
  1690. norpt:    call    decode
  1691.     rnz            ;EOF? <A>=1AH
  1692.     cpi    dle        ;Run encoding flag?
  1693.     jnz    norun
  1694. ;            Handle DLE
  1695.     call    decode        ;get count
  1696.     rnz            ;EOF? (is really error after DLE)
  1697.     ora    a
  1698.     jnz    run        ;Non-zero, real run 
  1699.     mvi    a,dle        ;dle is encoded as dle,0
  1700.     cmp    a
  1701.     ret
  1702. ;            ;Run encoding found
  1703. run:    dcr    a        ;Allow for char already retnd
  1704.     dcr    a        ; & this one
  1705.     sta    rcnt        ;Keep count yet to be retd
  1706.     lda    last        ;return second time
  1707.     cmp    a
  1708.     ret
  1709. ;            ;Normal char, no run active 
  1710. norun:    sta    last        ;This may be the start
  1711.     cmp    a
  1712.     ret
  1713. ;
  1714. ;
  1715. ;            Read bits and decode to char
  1716. ;             note this version uses 3 bytes per node
  1717. ;             not 4.
  1718. ;             The first byte in each node is a flag byte
  1719. ;              .... x... - left node contains EOF marker
  1720. ;              .... .x.. - right node contains EOF marker
  1721. ;              .... ..x. - left node contains char
  1722. ;              .... ...x - right node contains char
  1723. ;
  1724. decode:    lxi    d,0        ;Set to node zero in table
  1725.     lda    bitbuf        ;Get bits from bit buffer
  1726.     mov    c,a
  1727. bitlp:    lda    bitlft        ;Any bits remaining? 
  1728.     ora    a
  1729.     jnz    nxtbit        ;Yes - go use
  1730.     push    d
  1731.     call    getc        ;No - replenish bit buffer
  1732.     jnz    badr        ;Unexpected eof
  1733.     pop    d
  1734.     mov    c,a
  1735.     mvi    a,8        ;Set as 8 bits inbuffer 
  1736. nxtbit:    dcr    a
  1737.     sta    bitlft        ;Save no of bit remaining 
  1738.     lxi    h,SQTREE    ;Set to node 0, left child ptr
  1739.     dad    d
  1740.     dad    d
  1741.     dad    d        ;Add in node no (4 bytes/node)
  1742.     mov    b,m        ;Get flag byte
  1743.     inx    h        ;Step to left child pointer
  1744.     mov    a,c        ;Get input bits 
  1745.     rrc            ;Shuffle LOW-ORDER bit to Carry
  1746.     mov    c,a
  1747.     mov    a,b        ;Get flag byte 
  1748.     jnc    getn3        ;Zero input bit,leave at left
  1749.     inx    h        ;add 1 to point to right child pointer
  1750.     add    b        ;Normalize wanted flags to .... x.x.
  1751. getn3:
  1752.     mov    e,m        ;Pick up child or char
  1753. ;                <D> should always remain zero 
  1754.     ani    1010B        ;Mask unwanted bits
  1755.     jz    bitlp        ;Reg child pointer
  1756. ;            Got to char or eof
  1757.     ani    1000B        ;End of file marker?
  1758.     jnz    goteof        ;Yes - get out with eof
  1759.     mov    a,c
  1760.     sta    bitbuf        ;Save bit buffer
  1761.     mov    a,e        ;Get decoded char (neg)
  1762.     ret
  1763. ;
  1764. ;            Exit on reg eof
  1765. goteof:
  1766.     mvi    a,eof
  1767.     ora    a
  1768.     ret
  1769. ;
  1770. ;            ;Get input word (lo/hi, unencoded)
  1771. getw:    call    getc
  1772.     jnz    badr        ;Unexpected eof
  1773.     push    psw
  1774.     call    getc
  1775.     jnz    badr        ;Unexpected eof
  1776.     mov    h,a
  1777.     pop    psw
  1778.     mov    l,a
  1779.     ret
  1780. ;
  1781. erext:
  1782. badr:    call    CDISP
  1783.     db    cr,lf,'EOF?',cr,lf,0
  1784.     jmp    EXIT
  1785. ;
  1786. ;            Get single (unencoded) char
  1787. getc:    lhld    inbufu
  1788.     xchg
  1789.     lhld    inbufs
  1790.     call    cmphlde        ;End of input buffer?
  1791.     jz    getrf        ;Yes
  1792. getc1:
  1793.     mov    a,m        ;No get next byte
  1794.     inx    h
  1795.     shld    inbufs        ;Save addr of next byte
  1796.     cmp    a
  1797.     ret
  1798. ;
  1799. ;            Refill input buffer
  1800. ;
  1801. getrf:
  1802.     lda    SQEOF        ;Is there anything else?
  1803.     ora    a
  1804.     jz    getok
  1805.     call    CDISP
  1806.     db    cr,lf,'EOF',cr,lf,0
  1807.     jmp    EXIT
  1808. getok:
  1809.     lhld    SECCNT        ;Save sector count (decoded buffer only)
  1810.     push    h
  1811.     lxi    h,SQBUF        ;Set input buffer as empty,
  1812.     shld    inbufs        ;_and start of buffer
  1813.     xchg            ;DE> buffer, next sector locn
  1814.     lhld    SQBUFE        ;End of input buffer
  1815.     shld    inbufu        ;Assume no end of file for now
  1816.     mov    a,l
  1817.     sub    e
  1818.     mov    l,a
  1819.     mov    a,h
  1820.     sbb    d        ;Calc buffer size
  1821.     mov    h,a
  1822.     dad    h        ;Convert to no of sectors
  1823.     mov    b,h        ;No of sectors to read
  1824. ;                # sectors limited to 100 max (<B>=0)
  1825.     lhld    FCBCRR        ;No of 1st sector to read
  1826.     shld    SQBSC1
  1827.     call    FILBU1        ;Read sector into SQBUF
  1828. ;                <B> no of sectors not read if eof
  1829. ;                HL> 128
  1830. ;                DE> last sector read, or after if eof
  1831.     lhld    FCBCRR        ;Get next SQ sector no
  1832.     shld    NXTSQS
  1833.     mov    a,b        ;Did we fill buffer?
  1834.     ora    a
  1835.     jz    getrf2        ;yes - no eof
  1836.     xchg            ;Eof, adjust buffer end marker
  1837.     shld    inbufu        ;Mark end of buffer used
  1838.     sta    SQEOF        ;& flag eof
  1839. ;
  1840. ;            Input buffer re-filled
  1841. getrf2:
  1842.     pop    h
  1843.     shld    SECCNT        ;Restore sector count (decoded buffer only)
  1844.     lhld    inbufu        ;Get end of buffer
  1845.     xchg
  1846.     lhld    inbufs        ;Get start of buffer
  1847.     call    cmphlde        ;Something there?
  1848.     jc    getc1        ;Yes - go for char
  1849.     jmp    erext        ;No - read past eof or empty file
  1850. ;
  1851. ;end of baseline USQ code
  1852. ;
  1853. otbufe:    dw    0        ;End of decoded char buffer
  1854. inbufs:    dw    0        ;Start of input buffer
  1855. inbufu:    dw    0        ;End of used part input buffer
  1856. SQBUFE:    dw    0        ;End of input buffer
  1857. ;
  1858. nxtadr:    dw    DSKBUF        ;Next byte in output buffer 
  1859.                 ; also used when loading tree
  1860. bitlft:    ds    1        ;No of bits left in bit buffer
  1861. rcnt:    ds    1        ;Run count remaining (DLE)
  1862. filchks:ds    2        ;Checksum read from file
  1863. last:    ds    1        ;Last reg char decoded
  1864. bitbuf:    ds    1        ;Latest 8 bits (encoded) from input file
  1865. numvals:ds    2        ;No of nodes in encodng tree
  1866.     ENDIF
  1867. ;
  1868. ;    Memory allocation
  1869. ;
  1870. SECCNT:    DW    0        ;number of sectors read into buffer
  1871. LINMAX:    DB    SCROLN        ;number of write lines on console
  1872. CHRMAX:    DB    MAXCHR-1    ;number of characters to display per line
  1873. CHRMIN:    DB    0        ;character to start displaying on line
  1874. CHRCNT:    DS    1        ;character number in line
  1875. LINCNT:    DS    1        ;line number on write or move back in buffer
  1876. TOPBUF:    DB    0        ;Top of file is now in buffer
  1877. ;                 Z - yes, NZ - no
  1878. ;
  1879.     IF    SQUEEZE
  1880. NXTSEC:    DW    0        ;Next (unsqueezed) sector not yet in BSKBUF
  1881. ;                 set (and used) only by FILSQ
  1882. SQFLG:    DB    0        ;File is squeezed
  1883. SQEOF:    DB    0        ;End of file on squeezed file
  1884. SQREWD:    DB    0        ;Flag the SQ input file is being re-read
  1885. ;                 buffer refill rtn (getrf) to set inbufs
  1886. ;                 as per offset in SQBYT, and pre-load
  1887. ;                 bit buffer. Bit buffer to be adj
  1888. ;                 as per Bitlft
  1889. SQBYT:    DW    0        ;Offset of first data byte in SQ buffer
  1890. SQBSC1:    DW    0        ;No of 1st sector in SQ buffer
  1891. NXTSQS:    DW    0        ;No of last sector in SQ buffer
  1892.     ENDIF
  1893. ;
  1894. ;
  1895.     IF    LIBRARY
  1896. namexc:    db    (MAXCHR/14)-1    ;No of directory names across display
  1897.     db    0        ;No of names so far
  1898. dirsiz:    db    0        ;# of members possible in directory
  1899. memnam    db    0        ;Member name specified on command line
  1900. SCZERO:    DW    0        ;First sector for member
  1901. SCLAST:    DW    0FFFFH        ;Last sector for member (included in member)
  1902. ;                 SCZERO and SCLAST are relative in file
  1903. LBFLG:    DB    0        ;File is a library file
  1904. memfcb:    DS    12        ;Member name here
  1905.     ENDIF
  1906. ;
  1907.     DS    60        ;stack area
  1908. STACK:    DS    2        ;old stack saved here
  1909. DSKBUF:    EQU    $        ;disk buffer area above the program
  1910. ;
  1911. ENDBUF    EQU    DSKBUF+MAXSEC*128
  1912. ;
  1913.     IF    SQUEEZE
  1914. SQTREE    EQU    ENDBUF        ;Space for SQ decoding tree
  1915. SQMAP    EQU    SQTREE+256*3
  1916. ;                Space for SQ buffer mapping table
  1917. ;                contains sq sect #, sq byte & bit offset
  1918. ;                for every time DSKBUF was filled
  1919. ;                1st entry contains index to latest mapping
  1920. ;                triplet
  1921. ;                To handle run compr straddling buffer end,
  1922. ;                should also store rcnt & last 
  1923. SQBUF    EQU    SQMAP+100*4    ;(allows for 100 8k buffers)
  1924. ;                Input (squeezed) buffer
  1925. ;                Runs up to top of free mem 
  1926.     ENDIF
  1927. ;
  1928.     END    TPA
  1929.