;  Kaypro BISHOW v3.21 - buffered bi-directional file scroll utility
;
; KPBISHOW is now completely compatible with standard Wordstar control
; keys and uses the Kaypro arrow keys for +/- scrolling and right and
; left margin control
;
; Ver 3.21, 8 Dec 84, Steve Sanders, Tampa, FL
;       - Oops, my mistake with the filename printing twice.
;         Removed (sic) code that I had added (it was late folks).
;         Call status line in one shot now like it should be.
;         Future rev planned to display current memory page number
;         and allow going directly to any given page number with
;         a CTRL-G nn  command.  Also go all the way to the back
;         of the file.
;
; Ver 3.20, 8 Dec 84, Steve Sanders, Tampa, FL
;       - Added the name of file being displayed on 25th line
;         
; Ver 3.10, 5 Dec 84, Steve Sanders, Tampa, Fl
;       - Added 25th line display of program name, vers #, and
;         "enter ? for help menu".  Stripped out all non-Kaypro
;         equates and short version code.
;
; Ver 3.00kp, 2 Dec 84, Steve Sanders, Tampa, Fl
;       - This version is for video-able Kaypros only
;         Made command structure the same as Wordstar for scrolling
;         forward and backward and also for advancing one line forward
;         or backward.  Text scroll is completely controlled by the
;         Kaypro cursor keys now - up, down, left, and right.
;         Changed help menu accordingly, added commands to menu that
;         were always in the old code but not documented.  Removed the
;         GRAF toggles as there are no line drawing routines for the
;         Kaypro used and other graphics don't need the GRAF byte toggled.
; 
; Ver 2.09KP, 25 Sep 84, Jim Gronek, Phoenix, Arizona 
;	- Added equates for Kaypro 2/4/10, reverse video codes on help
;	  command (?), modified exit routines to re-enable cursor
;         even if filename not specified to BISHOW, added automatic
;	  toggle for GRAF byte with ZCPR2/3 on K10's
;
; Ver 2.09, 7 Jan 84, Frans van Duinen, Toronto, Ont
;	- Modified USQ routines for higher speed (+10%) and
;	 less memory usage.
;	- made USQ code optional through conditional assembly
;	- fixed a bug introduced with 2.08 and SHORT=TRUE 
;	  (resulted from ASM's inability to nest IF/ENDIF) 
;	- fixed a bug  that reset FCBEX after open, whenever
;	  sector 0 was read, (this resulted in BDOS assuming that
;	  the current extent, whose allocation group nos were still
;	  in the FCB, was the correct one. 
;	- Changed exit to clear screen only on Q or ^C exit,
;	  to leave any messages visible
;	- Made wait after clear screen a cond assembly option
;
; Ver 2.08, 2 Jan 84, Frans van Duinen, Toronto, Ont
;	- added squeezed file capability
;	- added sidewise scrolling on ^I, ^L, steps of 8
;	- Osborne support for cursor keys, clr scr & scr size
;	- Changed FILBAK rtn to recognize top of file
;	- Set up flag to avoid unnecessary re-reading of
;	  top of file 
;
;	The unsqueeze code was lifted from the USQ base code
;	by Dave Rand (Edmonton, Alberta) as adapted for LTYPE1
;	by S.Kluger (El Paso,Texas)
;	The code was lifted to allow continued use of ASM.COM 
;
; ** Original program code written by Phil Cary  23 Aug 82
;
; BISHOW is a  buffered,  bidirectional  version  of  SHOW.ASM
; which first appeared in Interface Age, November, 1981.  That
; program  could  only  scroll  forward  in  a  file, and read
; sectors from disk one at a time as they  were  sent  to  the
; console.   I  used SHOW frequently to take a quick look at a
; file without loading a  big  text  editor,  and  to  examine
; another  file  with the RUN command while in Wordstar.  TYPE
; does not work since it is not a file that Wordstar can  load
; and run.
;
; It was annoying when I went past the point I was looking for
; in a file with SHOW, and could not go backwards.  Thus, this
; bidirectional  version  which  uses  random access reads. In
; addition, buffering was added so that  the  number  of  disk
; reads  would  be  reduced,  and  moving  back and forth in a
; moderate sized file would be speeded up.  There is  a  trade
; off between the size of the buffer and the length of time it
; takes to refill the buffer which should be set to the user's
; preference.
;
; There are several customizing items in this program.  One is 
; the equate "maxsec" which sets the buffer size.   Another is 
; the  string  in the subroutine "clrscr" just after  the  org 
; statement.   This should be changed to erase the screen  and 
; home  the cursor for the user's terminal.   The program,  as 
; written,  requires a terminal with an erase screen and  home 
; cursor  function.   Some  terminals  do not allow  the  80th 
; column  to be filled without going to the  next  line.   For 
; this reason, the screen width ("maxchr") initially is set to 
; 79.   The screen sizes can be changed using the "S" (screen) 
; command.  The parameters that can be changed are the maximum 
; column  displayed ("maxchr"),  the minimum column  displayed 
; (allowing  you  to "window" the output),  and the number  of 
; lines ("scroln").   A zero for the maximum column  displayed 
; will  give and unlimited screen width.   The maximum  column 
; displayed  and  the number of lines can be set when  calling 
; BISHOW,  e.g.,  "BISHOW file.nam 79 24" will give 79 columns 
; and 24 lines,  and "BISHOW file.nam 79" will give 79 columns 
; with the default number of lines.  The last customizing item 
; is the "short" equate.   If this is chosen, the multiplicity 
; of command forms is not allowed (see the beginning to change 
; the  commands  used),  and certain messages  are  shortened.  
; This will allow BISHOW to fit into a 1K area.  If "short" is 
; false, the program is slightly over 1K.  Finally, direct I/O 
; to the console is used to avoid echoing the commands to  the 
; console as the CP/M write console function does.
;
; Just  a  small contribution to the public domain software as
; partial payment for the many fine and  educational  programs
; the system has given me.  Phil Cary.
;.........
;
FALSE	EQU	0
TRUE	EQU	NOT FALSE
;
; this code is now for Kaypro only -
;
KAYPRO	EQU	TRUE		;assemble for Kaypro 2/4/10
;
SQUEEZE	EQU	TRUE		;Generate code to handle squeezed files 
NOWAIT	EQU	TRUE		;Do not wait after clear screen
;
;	Operational equates
;
MAXSEC	EQU	32		;number of sectors in buffer
SIGNAT	EQU	0FF76H		;Signature for SQ files
DLE	EQU	090H		;Char flag for run compression (SQ)
;
;
	IF	KAYPRO
SCROLN	EQU	24		;number of lines per scroll
MAXCHR	EQU	79		;number of characters per line
ARWLFT	EQU	08H		;Cursor left key (backspace)
ARWUP	EQU	0BH		;Cursor up key (vert tab)
arwdwn	equ	0ah		;cursor down key (linefeed)
ARWRT	EQU	0CH		;Cursor right key (formfeed)
	ENDIF
;
;
BASE	EQU	0		;standard zero base CP/M
;
;	BDOS functions
;
CONOUT	EQU	2		;console write
OPEN	EQU	15		;open file
CLOSE	EQU	16		;close file
READR	EQU	33		;read file random access
STDMA	EQU	26		;set dma address
;
;	Page zero equates
;
WBOOT	EQU	BASE		;warm boot entry point
BDOS	EQU	WBOOT+5		;BDOS entry point
FCB	EQU	WBOOT+5CH	;default fcb drive number
CMDTAIL	EQU	WBOOT+80H	;location of command tail
FCBFN	EQU	FCB+1		;start of filename
FCBFT	EQU	FCB+9		;start of filetype
FCBEX	EQU	FCB+12		;current extent number
FCBCRR	EQU	FCB+33		;current record number, random access
TPA	EQU	WBOOT+100H	;transient program area
;
;	ASCII equates
;
ENDMSG	EQU	0		;null
BELL	EQU	7		;bell
BS	EQU	8		;Backspace
TAB	EQU	9		;tab
LF	EQU	0AH		;line feed
CR	EQU	0DH		;carriage return
EOF	EQU	1AH		;end of file
ESC	EQU	1BH		;escape
SPACE	EQU	20H		;space
;
;
	ORG	TPA
;
	JMP	START		;skip over next subroutine
;
CLRSCR: CALL	CDISP		;command to home cursor and clear to
	DB	1EH,17H,ENDMSG	;end of screen for Kaypro 2/4/10
;
	IF	NOWAIT
;
WAIT:	MVI	B,0		;waste time (may or may not be necessary)
;
WAIT1:	XTHL			;good time gobbeler!
	XTHL
	DCR	B
	JNZ	WAIT1
	RET			;return from clrscr
;
	ENDIF
;
HELP2:	; very fancy graphical help menu for the Kaypro
	CALL	CDISP
	DB	cr,lf
	DB	ESC,'B0'
	db	'     KPBISHOW v 3.21   Available Commands (same as Wordstar)   '
	db	'  ',cr,lf,' ',esc,'B1'
	db	' ^C,Space bar,F, or C/R=forward a page     ^R or B=back 1 page '
	DB	esc,'C1',' ',cr,lf,' ',esc,'B1'
	DB	' ^Z,+,arrow-down=forward 1 line      ^W,-,arrow-up=back 1 line '
	db	esc,'C1',' ',cr,lf,' ',esc,'B1'
	db	' ^L or arrow-right=8 cols right   ^H or arrow-left=8 cols left '
	db	esc,'C1',' ',cr,lf,' ',esc,'B1' 
	db	' ^S or S=set the screen parameters       Q or X=exits program  '
	DB	ESC,'C1',' ',cr,lf,' ',esc,'B1'
	db	'      Any other keys pressed will display this help menu       '
	db	esc,'C1',' ',cr,lf
	db	'                 Steven L. Sanders   08 Dec 84                 '
	db	'  '
	DB	esc,'C0',CR,LF,ENDMSG
	JMP	GETCMD
;
STATUS:		; status line display for the Kaypro
	CALL	CDISP
	DB	ESC,'C7',1AH	;disable status line and clear screen
	DB	ESC,'B6'	;save cursor position
	DB	ESC,'B7'	;enable status line
	DB	ESC,'=8 '	;position cursor to 25,0
	DB	ESC,'B0'	;inverse video mode
	DB	ESC,'B1'	;dim mode
	DB	' *KPBISHOW* '
	DB	ESC,'C1'	;dim off
	DB	' Viewing file:'
	DB	endmsg

; print filename routine
;
	lxi	h,cmdtail	;get filename from command tail
	mov	b,m		;get number of chrs
	inx	h		;point at first chr
	inr	b
prtfn1: mov	a,m		;get the chr
	call	co		;output it
	inx	h		;move pointer
	dcr	b		;decrement the b reg
	jnz	prtfn1		;if not 0 then loop till done
;
	call	cdisp		;now finish rest of status line
	db	' '
	db	esc,'B1'	;dim mode
	db	esc,'B2'	;blink on 
	db	'   ? for help '
	db	esc,'C2'	;blink off
	db	'  S. Sanders  12/08/84 '
	db	esc,'C1'	;dim off
	DB	ESC,'C0'	;inverse video off
	DB	ESC,'C6'	;recall cursor position
	DB	ENDMSG
	ret

;
; start of program (finally)
;
START:	LXI	H,0		;get ccp's stack
	DAD	SP
	SHLD	STACK		;save old stack for later
	LXI	SP,STACK	;set new stack
	LXI	H,CMDTAIL	;point to command tail
	MOV	B,M		;get number of char in tail
	INX	H		;point to first character
	INR	B
;
EATSP:	MOV	A,M		;get character if there is one
	INX	H
	DCR	B		;b=number of characters left
	JZ	OPENF		;no more characters
	CPI	SPACE		;ignore spaces
	JZ	EATSP
;
FILNAM:	MOV	A,M		;get characters in file name
	INX	H
	DCR	B		;b=number of characters left
	JZ	OPENF		;only file name in tail
	CPI	SPACE		;wait for next space
	JNZ	FILNAM
	LXI	D,CHRMAX	;point to chr/line
	CALL	GETNBR		;get number of characters/line
	JC	HELP		;invalid number
	LXI	D,LINMAX	;point to number of lines
	CNZ	GETNBR		;call only if characters still in
				;__command tail
	JC	HELP		;invalid number
;
OPENF:	CALL	OPNFIL		;open file in default fcb
;
	CALL	STATUS		;display status line if file open ok
;
OPENF1:
	IF	SQUEEZE
;
	CALL	CHKSQ		;Check for squeezed, init if
;
	ENDIF
;
WRTFWD:	XRA	A		;get a 0
	STA	LINCNT		;store in line count
	STA	CHRCNT		;store in character count
;				Do not reset the current extent!!!
;				BDOS will switch extents only if the no
;				specified ( <FCBEX> ) does NOT agree with
;				the wanted no <FCBCRR>. 
	STA	FCBCRR		;zero current record
	STA	FCBCRR+1	;__both bytes
	STA	FCBCRR+2	;__and the overflow
	CALL	CLRSCR		;erase the screen
;
WRTFW0:	CALL	FILBUF		;fill the disk buffer
WRTFW3:
	LXI	H,DSKBUF	;point to beginning of buffer
;
WRTFW1:
	MOV	A,M		;get a character
	CPI	EOF		;see if eof
	JZ	GETCMD		;yes, wait for command
	INX	H		;bump pointer
	ANI	7FH		;strip high bit
	CPI	'L'-40H		;filter form-feeds
	JZ	FILTER		;__commonly found in .PRN files
	CALL	CO1		;put it on console
	CPI	CR		;see if end of line
	JZ	FWDCNT		;yes, adjust line count
;
WRTFW2:	LXI	D,ENDBUF	;get end of buffer address
	CALL	cmphlde		;Is HL> gt DE> (end of buff)
;				; Note test is LT now, not NE (v1.81)
	JNC	WRTFW0		;refill buffer and start over
	JMP	WRTFW1		;else, continue with next character
;
HELP:	CALL	CDISP
	DB	1ah,ESC,'B0'
	DB	'  Kaypro BISHOW vers 3.21  '
	DB	ESC,'C0',CR,LF,LF
	DB	'Usage:  BISHOW d:filename.typ [cols [lines]]',CR,LF,cr,lf
	DB	'Specify entire filename.typ - no wildcards allowed',cr,lf,lf
	DB	'Columns default to  79',cr,lf
	DB	'Lines per screen to 24',cr,lf
	DB	ENDMSG
	JMP	EXIT1
;
FILTER:	PUSH	PSW		;save status
	MVI	A,'^'		;print '^' in front
	CALL	CO1		;__of control character
	POP	PSW		;restore status
	ADI	40H		;mask into displayable char
	CALL	CO1		;display filtered control char
;
FWDCNT:	LDA	LINCNT		;get number of lines displayed
	INR	A		;bump it
	STA	LINCNT		;__and store it
	MOV	D,A		;save lincnt
	LDA	LINMAX		;get max number of line
	CMP	D		;compare with line count
	JNZ	WRTFW2		;if not there, continue, else get command
	XRA	A		;zero the
	STA	LINCNT		;__line count
;
GETCMD:	PUSH	H
	PUSH	D
	PUSH	B
;
	IF	KAYPRO
	CALL	CDISP
	DB	ESC,'C4',ENDMSG	;disable cursor
	ENDIF
;
GETCM1:	MVI	C,6		;direct console I/O
	MVI	E,0FFH		;__set up for input
	CALL	BDOS
	ORA	A		;loop till char avail
	JZ	GETCM1
	POP	B
	POP	D
	POP	H
	CPI	'a'		;change command to
	JC	GETCM2		;__upper case
	CPI	'z'+1
	JNC	GETCM2
	XRI	20H		;is lower case, make upper case
;
GETCM2:		; get the command from keyboard
;
; go to top of the file?
;
	CPI	'1'		; 1 means goto 1st line
	JZ	WRTTOP		;Test if top in buffer
;
; help?
;
	CPI	'?'		;help request
	JZ	HELP2
;
; forward a page ( Space bar, F, ^C, or C/R )
;
	CPI	' '		;more use space
	JZ	WRTFW1
	CPI	'F'		;scroll forward?
	JZ	WRTFW1		;br if yes
	CPI	'C'-40H		;wordstar uses ^C
	JZ	WRTFW1
	cpi	cr		;also c/r goes forward a page
	jz	wrtfw1
;
; back a page ( B or ^R )
;
	CPI	'B'		;scroll backward?
	JZ	WRTBAK
	CPI	'R'-40H		;wordstar uses ^R
	JZ	WRTBAK
;
; next line forward ( +, ^Z, or Arrow-down key )
;
	cpi	'+'		;1 for 1 more line?
	jz	wrtnxt
	cpi	'Z'-40H		;wordstar uses ^Z
	JZ	WRTNXT
	cpi	arwdwn		;cursor down?
	jz	wrtnxt
;
; back a line ( -, ^W, or Arrow-up key )
;
	cpi	'-'		;minus key?
	jz	wrtprv
	CPI	'W'-40H		;scroll prev line?
	JZ	WRTPRV
	CPI	ARWUP		;Cursor up?
	JZ	WRTPRV		;yes, back-up a line
;
;
; exit program, clear screen ( Q or X )
;
	CPI	'Q'		;Q for quit?
	JZ	EXITCL
	cpi	'X'		;was it an X
	jz	exitcl
;
; set new screen paramaters ( S or ^S )
;
	CPI	'S'		;set screen parameters
	JZ	SETSCR
	cpi	'S'-40H
	jz	setscr
;
; adjust margins ( Arrow-left, Arrow-right, or M )
;
	CPI	ARWLFT		;Cursor left?
	JZ	ADJMM
	CPI	ARWRT		;Cursor right?
	JZ	ADJMM
	cpi	'M'		; m for margins?
	jz	adjmm
;
	JMP	HELP2		;if none of these, display built-in help menu
;
;...........
;			Go to top of file
WRTTOP:
	LDA	TOPBUF		;Get top in buffer flag
	ORA	A
	JNZ	WRTFWD		;No - the hard way
	CALL	CLRSCR		;erase the screen
WRTTO1:
	XRA	A
	STA	LINCNT		;Clear lines put so far
	JMP	WRTFW3		;Buffer contains top sectors
;
;			Write one more line
WRTNXT:	LDA	LINMAX
	DCR	A		;fool wrtfw1 to only write one line
	STA	LINCNT
	JMP	WRTFW1
;			Back up one line
WRTPRV:	LDA	LINMAX		;back up one screen + 1 line
	INR	A
	JMP	WRTBK0
;			Back up full screen
WRTBAK:	LDA	LINMAX		;get screen line count
	ADD	A		;__multiply by 2
;
WRTBK0:	INR	A		;__and add 1
	STA	LINCNT		;__to backup to previous page
	CALL	CLRSCR		;clear the screen
;
WRTBK1:	LXI	D,DSKBUF	;get address of start of buffer start
	CALL	cmphlde		;Is HL> LT DE> (start of buff)
;				; Note test is LT now, not NE (v1.81)
	JC	FILBAK		;Go refill buffer
;
WRTBK2:	MOV	A,M		;get a character
	ANI	7FH		;strip high bit
	DCX	H		;decrement buffer
	CPI	CR		;see if end of line
	JZ	BAKCNT		;__or form-feed
	CPI	'L'-40H		;__and adjust line count if so
	JNZ	WRTBK1		;else, loop if not
;
BAKCNT:	LDA	LINCNT		;else, get number of lines to move back
	DCR	A		;__and decrement it
	STA	LINCNT		;__store it
	JNZ	WRTBK1		;__and loop if not there
	INX	H		;else bump pointer
	INX	H		;__to account for dcx
	JMP	WRTFW1		;and go write a screen
;
FILBAK:
;			Test for top of file
	LDA	TOPBUF		;Get top in buffer flag
	ORA	A
	JZ	WRTTO1		;Yes - start of file in buffer
;			Start of file not in buffer, step back
	LHLD	SECCNT		;Get no of sectors last read
	LXI	D,MAXSEC	;get the buffer size
	DAD	D		;add them
	XCHG			;__and put them in DE
	LDA	FCBCRR		;subtract low order byte 
	SUB	E		;__from current record count
	STA	FCBCRR		;__and store in current record count
	LDA	FCBCRR+1	;same with high order byte
	SBB	D		;__but with borrow
	JM	WRTFWD		;if beyond beginning of file, start over
	STA	FCBCRR+1	;else, store high order byte
	CALL	FILBUF		;fill the buffer
	LXI	H,ENDBUF	;__and point to end of buffer
	CALL	CLRSCR		;clear the screen
	JMP	WRTBK2		;continue moving back in file
;
;			;Fill buffer from spec'd sector
FILBUF:
	MVI	B,MAXSEC	;number of sectors to resd
FILB1S:
	LXI	D,DSKBUF	;load start of disk buffer
	LXI	H,0		;zero out the
	SHLD	SECCNT		;__number of sectors in buffer
	LHLD	FCBCRR		;Is this top of file?
	MOV	A,H
	ORA	L
	STA	TOPBUF		;Set top of file in buffer flag
;				; Z - top, NZ - not top 
	IF	SQUEEZE
	LDA	SQFLG		;Is this a squeezed file
	ORA	A
	JNZ	FILSQ		;Yes -
	ENDIF
;
FILBU1:	PUSH	H		;save all
	PUSH	D		;__registers from
	PUSH	B		;__BDOS clobber
	MVI 	C,STDMA		;set dma to
	CALL	BDOS		;__disk buffer
	LXI	D,FCB		;set up to read
	MVI	C,READR		;__a record
	CALL	BDOS		;do it
	ORA	A		;read OK?
	LHLD	FCBCRR		;get current record number
	INX	H		;__bump it
	SHLD	FCBCRR		;__and save it
	LHLD	SECCNT		;get sectors in buffer
	INX	H		;bump it
	SHLD	SECCNT		;store it
	POP	B
	POP	D
	POP	H
	JNZ	RDERR		;no, last sector read
	DCR	B		;decrement it
	RZ			;if done return
	LXI	H,128		;else, add 128 to
	DAD	D		;__dma address
	XCHG			;put it in de
	JMP	FILBU1		;read another sector
;
	IF	SQUEEZE
;
;			Fill buffer from squeezed file
;			This rtn handles mapping from unsq sector #
;			to sector, byte & bit in sq stream
;			on input FCBCRR contains wanted sector no,
;			( no allowance made for sectors # over 65535)
;			<B> contains no of sectors wanted
;			DE> buffer where sectors wanted,
;			 ignored in this version, always full DSKBUF
FILSQ:
	LHLD	FCBCRR		;Get # for 1st sector wanted
	XCHG
	PUSH	D		;Save to restore after unsq
	LHLD	NXTSEC		; & 1st sector after buffered ones  
	CALL	cmphlde		;Consecutive?
	JZ	USQNXT		;Yes - fine
	JNC	USQBAK		;No - lower
;			;Next sect after latest but not consec
	CALL	CDISP
	DB	CR,LF,'Program failure, non-contiguous sectors requested'
	DB	CR,LF,'from unsqueeze rtn',CR,LF,0
	JMP	EXIT		;Should never happen
USQBAK:			;Going backward
	MOV	A,D		;All the way?
	ORA	E
	JNZ	USQNO1		;No - MUST be prev!!!
	LXI	H,SQMAP+2+8	;Yes - reset SQMAP index to #3
	SHLD	SQMAP
USQNO1:
	LHLD	SQMAP		;Get index into mapping table
	LXI	D,-8		;Step back from next, past current to prev
	DAD	D
	SHLD	SQMAP		; & save updated index for next
	MOV	E,M		;Get SQ sector no
	INX	H
	MOV	D,M
	INX	H
	MOV	C,M		;Get byte offset
	INX	H
	MOV	A,M		; & bit offset
	STA	bitlft
	XRA	A
	STA	rcnt		;No runs in progress
;				(assumption)
	STA	SQBYT+1		;Set offset 1st data byte
	MOV	A,C
	STA	SQBYT		;For now offset within sector only
	LHLD	SQBSC1		;Get no of first SQ sector now in buffer
	XCHG			;<HL> wanted 1st sector, <DE> actual 1st
	CALL	cmphlde		;Is 1st buffer sector low/equal 1st data sect?
	JNC	USQ1OK		;Yes - first wanted sector SQ in buffer
;				 Max header 1035 bytes + file name)
;			Force reload of SQ buffer
	SHLD	NXTSQS		;No - 1st data sector b/4 1st buffer sect
;				 (note is probab not sector 0
;				 because of header, eg decoding tree)
	MVI	A,1		;Set rewind with I/O
	STA	SQREWD		;Set rewind flag
;				 SQBYT contains offset of 1st data byte
	XRA	A
	STA	SQEOF		;Reset end of file on SQ
;				Leave current extent alone. This is how
;				BDOS knows how to switch extents. It checks
;				if the current extent no agrees with
;				the wanted record.
	STA	FCBCRR+2	; & count overflow, should not be necessary
	MOV	D,A
	JMP	USQNX1		;Go adj buffer pointer
;				(NOP since <DE>=0
;			;SQ text still in buffer
USQ1OK:
;				<DE> # of 1st sector in SQ buf
;				<HL> # of wanted SQ sector 
;				(Max 100H SQ sectors in buffer)
	MOV	A,L
	SUB	E
	RAR			;Convert to pages (100H)
;				 Know Cy=0 in
;				 leaves Cy if odd no of sects
	MOV	D,A
	MVI	A,0		;Do not disturb Cy
	RAR			;Pu carry (now 80H or 00H) 
USQNX1:
	MOV	E,A
	LHLD	SQBYT		;Get offset of 1st data byte in wanted sect
	DAD	D		; --> offset in buffer
	LXI	D,SQBUF
	DAD	D		;Convert to absolute addr
	SHLD	inbufs		;& set as next byte to unsqueeze
;
USQNXT:			;Next sector consecutive
	LHLD	NXTSQS		;Get no of next SQ sector 
;				(in case read reqd)
	SHLD	FCBCRR
;			Build mapping table entry
	LHLD	inbufs		;Calc offset in buffer
	LXI	D,-SQBUF
	DAD	D
	MOV	C,L		;Keep offset within sector
	LDA	bitlft		;Get bit offset
	MOV	B,A
	ORA	A		;On byte boundary?
	MOV	A,C
	JNZ	NOTBBY		;No -
	INR	A		;Yes - no adj reqd
NOTBBY:
	ANI	7FH		;Ensure sector relative
	DAD	H		;Convert to sector no
	ORA	A		;Is next byte at start of sect?
	JNZ	SECTOK
	DCR	H		;Yes - step back one sector
SECTOK:
	DCR	A
	ANI	7FH		;& adj byte index
	MOV	E,H
	MVI	D,0
	LHLD	SQBSC1		;# of 1st sector in buffer
	DAD	D
	XCHG			;<D> absolute SQ sector no
	LHLD	SQMAP		;Get index
	MOV	M,E		;Save abs SQ sector no
	INX	H
	MOV	M,D
	INX	H
	MOV	M,A		;Save sector relative byte offset
	INX	H
	MOV	M,B		;Save bitlft
	INX	H
	SHLD	SQMAP		;Save new index
	CALL	CDISP		;Show msg where is
	DB	'>>> Unsqueezing text <<<',ENDMSG
;				Corrupts display if aft CR but b/4 LF
	CALL	filusq		;Fill unsq buffer
;				returns NZ on EOF
;				SQEOF set as well then
	CALL	CDISP		;Remove msg just displayed,
;				 assumes BS across start of line if reqd
	DB	BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS
	DB	BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS
	DB	'                        '
	DB	BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS
	DB	BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,BS,0
	LHLD	FCBCRR		;Get no of next SQ sector
	SHLD	NXTSQS
	LHLD	nxtadr		;Calc # of unsq sectors in buf
	LXI	D,-DSKBUF	;(as neg no)
	DAD	D		;Calc length
	DAD	H		; & convert to sectors in <H>
	MOV	L,H
	MVI	H,0
	SHLD	SECCNT		;Save # of sectors in DSKBUF
	POP	D		;Get FCBCRR as passed by calling rtn
	DAD	D		; & calc new one
	SHLD	FCBCRR
	SHLD	NXTSEC
	RET
;
	ENDIF
;
;
;We only get here if end of file
;
RDERR:	MVI	A,EOF		;get bogus eof
	STAX	D		;save at buffer end in case no eof in file
	XRA	A		;get a zero to direct to start of buffer
	RET			;__on ret
;
OPNFIL:	LDA	FCBFN		;point to first letter of filename
	CPI	' '		;anything there?
	JZ	HELP		;no, give help message
	XRA	A		;get a 0
	STA	FCBEX		;zero current extent
;				MUST open file on extent zero
	LXI	D,FCB		;file name in default fcb
	MVI	C,OPEN		;set up to open
	CALL	BDOS		;do it
	INR	A		;open OK?
	RNZ			;yes
	CALL	CDISP		;else, give error msg and quit
	DB	cr,lf,'File not found - check the DIR',7,cr,lf,ENDMSG
	JMP	EXIT1		;leave msg on screen on exit
;
GETNBR:	MOV	A,M		;get first digit
	INX	H
	DCR	B		;b=number of characters left in buffer
	RZ			;no digit
	CPI	SPACE
	JZ	GETNBR		;wait until next non-space
	PUSH	D		;save location to save number
	MVI	D,0		;initialize number
;
GNUM1:	SUI	30H		;change ASCII to number
	JC	INVNUM		;not a number
	CPI	10
	CMC
	JC	INVNUM		;not a number
	PUSH	PSW		;save number
	MOV	A,D		;multiply old number by 10
	ADD	A		;*2
	ADD	A		;*4
	ADD	A		;*8
	ADD	D		;*9
	ADD	D		;*10
	MOV	D,A
	POP	PSW		;restore new digit
	ADD	D
	MOV	D,A
	MOV	A,M		;get next digit
	INX	H
	DCR	B
	JZ	ENDNUM		;end of number
	CPI	SPACE
	JNZ	GNUM1
;
ENDNUM:	MOV	A,D		;save number
	DCR	A		;correct number for co routines
	XCHG			;set to restore save location
	POP	H		;restore save location
	MOV	M,A		;save digit
	XCHG			;put buffer location where it belongs
	MOV	A,B		;see if any characters left in buffer
	ORA	A		;zero if no characters in buffer
	RET
;
INVNUM:	POP	D		;correct stack
	RET
;
ASCIIN:	MVI	B,100		;divide by 100, then change
	CALL	DIVIDE		;__digit to ASCII and store at hl
	MVI	B,10		;divide by 10, then change
	CALL	DIVIDE		;__digit to ASCII and store at hl+1
	MVI	B,30H		;change ones place number
	ADD	B		;__to ASCII and store at hl+2
	MOV	M,A
;
CDISP:	XTHL			;exchange top of stack and HL
;
CDIS1:	MOV	A,M		;HL now pointing to db message
	ORA	A		;see if 0 at end of message
	INX	H
	JZ	CDIS2		;yes, restore stack and return
	CALL	CO		;no, print the character
	JMP	CDIS1		;__and loop
;
CDIS2:	XTHL			;get return address on top of stack
	RET			;__and return
;
CO:	PUSH	B		;Save the registers
	PUSH	D		;__from bdos
	PUSH	H		;__clobber
CO2:	PUSH	PSW
CO4:	MOV	E,A		;set up character
	MVI	C,CONOUT	;__to send to console
	CALL	BDOS		;do it
CO3:	POP	PSW
CO5:	POP	H		;restore
	POP	D		;__the registers
	POP	B
	RET
;
CO1:	PUSH	B		;Save the registers
	PUSH	D
	PUSH	H
	PUSH	PSW
	LXI	H,CHRCNT	;Get address of character count
	CPI	CR		;see if end of line
	JZ	ENDLIN		;update line information
	CPI	LF		;ignore linefeed
	JZ	CO4
	LDA	CHRMAX		;get maximum characters per line
	CMP	M		;see if too many char
	JC	CO3		;don't print character
	POP	PSW		;__and print character
	CPI	TAB		;fix chrcnt for tabs
	JZ	TABFIX
	INR	M		;increment character count
	MOV	E,A
	LDA	CHRMIN		;see if up to minimum display yet
	CMP	M
	MOV	A,E		;restore character
	JNC	CO5		;do not display character
	JMP	CO2		;finally, display character
;
ENDLIN:	MVI	M,0		;reset character count
	JMP	CO4		;print cr
;
TABFIX:	MVI	A,08H		;fix chrcnt for tabs
	ADD	M		;increment to next 8-count
	ANI	0F8H		;make into multiple of 8
;
TAB2:	SUB	M		;get number of space to go
	MOV	B,A
;
TAB1:	MVI	A,SPACE		;expand tab
	CALL	CO1
	DCR	B
	JNZ	TAB1		;still more spaces
	JMP	CO5		;exit routine
;
SETSCR:	PUSH	H
	PUSH	D
	PUSH	B
;
GETMAX:	LDA	CHRMAX		;get maximum number of characters
	INR	A
	LXI	H,HUNS
	CALL	ASCIIN		;put ASCII number in message		
;
	DB	CR,LF,'Maximum Column: '
;
HUNS:	DB	30H
	DB	30H
	DB	30H
	DB	' New? ',ENDMSG
	CALL	GETINP		;read input from console
	LXI	D,CHRMAX	;set new chrmax in memory
	CALL	GETNBR
	JC	GETMAX		;if error, repeat last message
;
GETMIN:	LDA	CHRMIN		;get minimum character display
	INR	A
	LXI	H,HUN
	CALL	ASCIIN		;put ASCII number in message		
;
	DB	LF,'Minimum Column: '
;
HUN:	DB	30H
	DB	30H
	DB	30H
	DB	' New? ',ENDMSG
	CALL	GETINP		;read input from console
	LXI	D,CHRMIN	;set new chrmax in memory
	CALL	GETNBR
	JC	GETMIN		;if error, repeat last message
;
GETLIN:	LDA	LINMAX		;get number of lines per display
	LXI	H,HUND
	CALL	ASCIIN		;put ASCII number in message		
	DB	LF,'Lines Displayed: '
;
HUND:	DB	30H
	DB	30H
	DB	30H
	DB	' New? ',ENDMSG
	CALL	GETINP		;read input from console
	LXI	D,LINMAX	;set new chrmax in memory
	CALL	GETNBR
	JC	GETLIN		;if error, repeat last message
 	POP	B
	POP	D
	POP	H
;
WRTSAM:	LDA	LINMAX		;write the same screen
	JMP	WRTBK0
;
;
GETINP:	MVI	A,5		;get set to read new maximum column
	STA	CMDTAIL
	MVI	C,0AH
	LXI	D,CMDTAIL
	CALL	BDOS		;get maximum column
	LXI	H,CMDTAIL+1	;now, change to ASCII
	MOV	B,M
	INX	H
	INR	B
	RET			;return with input in buffer
;
;			Adjust char min/max on cursor left/rt
ADJMM:
	PUSH	H
	CPI	ARWLFT		;Move left (decrease)?
				; set flag
	LDA	CHRMAX		;What is last char on line t/b displ
	MOV	H,A
	LDA	CHRMIN		; & 1st char to display
	MVI	L,8		;Scroll by 8
	JZ	ADJMMD		;Yes - adjust down
	ADD	L		;No - increase min, no limit
	PUSH	PSW
	MOV	A,L
	ADD	H		; & max
	JMP	ADJMMS
ADJMMD:
	SUB	L		;Display more to the left
	PUSH	PSW
	MOV	A,H
	SUB	L
ADJMMS:
	MOV	H,A		;<H> max
	POP	PSW		;<A> min
	CMP	H		;Wrap, (max< min)
	JNC	ADJMMX		;Yes - leave unchanged
	STA	CHRMIN
	MOV	A,H
	STA	CHRMAX
ADJMMX:
	POP	H
	JMP	WRTSAM		;Go write same screen
;
; 
DIVIDE:	MVI	C,'0'-1		;extract dividend of a div c
;
DIV1:	INR	C		;__and store in location pointed
	SUB	B		;__to by hl
	JNC	DIV1
	ADD	B
	MOV	M,C		;save ASCII digit
	INX	H		;bump pointer to next location
	RET
;
EXITCL:
;			Clear screen only on reg exit
	CALL	CLRSCR		;clear the screen
;
EXIT:	MVI	E,0FFH		;clear console of characters
	MVI	C,6		;direct console I/O
	CALL	BDOS		;__get any waiting characters
;
	IF	KAYPRO
	CALL	CDISP
	DB	ESC,'C7'	;disable status line
	DB	ESC,'B4',ENDMSG	;enable cursor display
	CALL	CLRSCR		;now clear whole screen
	ENDIF
;
	LXI	D,FCB		;close file
	MVI	C,CLOSE		;--in case this is MP/M
	CALL	BDOS
;
EXIT1:
		IF	KAYPRO
	CALL	CDISP		;re-enable cursor even if no file
	DB	ESC,'B4',ENDMSG	;specified to BISHOW
		ENDIF
;
	LHLD	STACK		;get old stack
	SPHL
	RET			;return to CCP
;
;
;			Compare <HL> to <DE>
;			 Z - equal; C - <HL> less than <DE> 
cmphlde:
	mov	a,h
	cmp	d
	rnz
	mov	a,l
	cmp	e
	ret
;
	IF	SQUEEZE
*******************************************************
* USQ support code				      *
* 10/12/83 by Dave Rand				      *
*******************************************************
;
;			Check for SQ file, init tree if so
 CHKSQ:
;			Initialize
	xra	a
	mov	l,a
	mov	h,l		;clear <hl>
	STA	SQFLG		;Make sure not set as squeezed yet 
	sta	SQEOF		; end of file on SQ
	sta	SQREWD		;Clear "rewinding" SQ file 
	sta	bitlft		;force init char read
	sta	rcnt		;and zero repeats
	shld	FCBCRR		;Clear next record
	sta	FCBCRR+2	; and overflow
	shld	numvals		;Clear # nodes
;
	lxi	h,SQBUF		;Set to input (squeezed) buffer 
	shld	inbufs
	shld	inbufu
	lxi	d,128
	dad	d
	shld	SQBUFE		;Force exit on full buff aft 1 sect
;				 causes the SQ buffer to contain
;				 sectors 1+ only (not zero),
;				 normally fine since sector 0 contains only
;				 header info. Sector 0 will be reread
;				 if contains data and needed  
	call	usqsig		;Read & val signature word
	RNZ			;Not SQ
	STA	SQFLG		;Yes - set flag
	lhld	0006		;Get top of memory
	lxi	d,sqbuf+100H*128 ;Limit buffer to max 100H
	call	cmphlde		; sectors (FILBUF uses 8 bit count <B>)
	JC	toplow		;use top
	xchg			;use limit 
toplow:
	shld	SQBUFE		;& store as full address 
	call	namlp		;Skip past name
	call	usqtbl		;Validate & load decoding tree
	jz	oak		;tree ok
	call	CDISP
	db	cr,lf,'Invalid decode tree size',cr,lf,0
	jmp	EXIT
oak:
	lxi	h,SQMAP+2	;Point to 1st entry 
	shld	SQMAP		;Set to 1at entry in SQ mapper
	ret
;			Read and validate signature word
usqsig:
	call	getw		;Read  1st word in file
	lxi	d,signat	;Get expected value
	call	cmphlde
	mvi	a,1		;Set code in case of error
	ret			;Exit with Z/NZ
;
;			Read & save checksum
rdchks:
	call	getw		;get cksum, and store
	shld	filchks
	ret
;			Read & skip name
namlp:	call	getc		;Loop to skip name
	jnz	erext		;I/O error or unexpected EOF
	ora	a
	jnz	namlp		;Not yet end of name
	ret
;
;			Load decoding tree
;			This version uses 1 byte abslute node indices
;			(1-ffH) and is thus limited to 255 nodes and 255
;			characters represented in the squeezed file.
;			(All different characters present in the original
;			file as well as any added through run encoding.
;			Runs of 3 or more consecutive identical characters
;			are encoded as char, DLE, count, where count
;			is a one byte field 00 - FFH) 
;
usqtbl:
 	call	getw		;Get no of nodes
	mov	a,h
	ora	l
	jz	nzexit		;Null tree
	shld	numvals
	mov	a,h		;Max 257, 256 char & spec eof
;				in this version allow for only 256
;				diff codes, every ASCII and non-ASCII
;				char would have to be present, or
;				run repeat counts 128-255 (every one)
	ora	a		;H/o byte should be zero
	jnz	nzexit
	lxi	d,SQTREE	;Set to decoding tree
nodelp:	shld	nxtadr		;Save no of nodes
	mov	a,h
	ora	l
	rz			;Done all nodes
	call	cvnode		;get node, falg byte in <H>,
;				 index/char in <L>
	push	h
	call	cvnode		;get second child/char
	pop	b
	mov	a,b
	ral			;Shift flags to 8, 4 posns 
	ora	h		;Combine in 1st child flags 
	xchg			;HL> SQTREE, <A>,<C>,<E> node 
	mov	m,a		;Store flags in table
	inx	h
	mov	m,c
	inx	h
	mov	m,e
	inx	h
	xchg			;DE> SQTREE
	lhld	nxtadr		;Nodes remaining
	dcx	h
	jmp	nodelp
;			Get encoded node
;			Our nodes contain 3 bytes:
;			- flag byte,
;			- left child index/char
;			- right child index/char
;			Nodes on input are 4 bytes,
;			with each half containing
;			an index (1-100h) or character,
;			where characters are encoded as
;			negative values -(char+1)
;			Eof is encoded as -(100h+1)
cvnode:
	push	d
	call	getw		;Get word, chld ptr or char
	pop	d
	mov	a,h
	ora	a
	rz			;Child index, <H>=0,<L>=index
	mov	a,l
	cma
	mov	l,a		;convert char to reg form
	mov	a,h		;get h/o byte again
	cma
	inr	a		;Conv to 1 if char, 2 if EOF
	mov	h,a
	cpi	1		;Was that reg char?
	rz			;Yes - complete
	adi	3		;No convert EOF flag to 0100
	mov	h,a
	ret

;			Exit with NZ flag
nzexit:
	mvi	a,2		;tree error
	ora	a		;Set NZ flag
	ret

;
;
;			Fill output buffer (unsqueezed char)
;
filusq:
	lda	SQREWD		;Rewinding SQ input?
	ora	a
	jz	norewd		;No
;			Reload SQ buffer
	lhld	inbufs
	push	h		;getrf resets
	call	getrf		;Yes - reload buffer & get 1st 8 bits
	pop	h
	shld	inbufs		;Set to first data byte to use
badj:
	mov	c,a
	lda	bitlft		;Get preset 1st wanted bit no
	mov	c,a
	mvi	a,8
	sub	b		; Calc adjmt reqd  
badjlp:
	dcr	a
	jz	badjfn		; bit adjust finished
	mov	b,a
	mov	a,c
	rrc
	mov	c,a
	mov	a,b
	jmp	badjlp
badjfn:
	sta	bitbuf
	xra	a
	sta	SQREWD		; & clear rewind flag
norewd:
	lxi	h,DSKBUF	;reset buffer pointer
	xra	a
buflp:
	shld	nxtadr		;Save as next byte in buffer
	rnz			;End of file (NZ flag)
;				 as set by GETNXT rtn below
	lxi	d,SQTREE	;Get end of input
	call	cmphlde		;buffer full (de < hl - not full)
	jnc	full		;buffer is full
	call	getnxt		;Get next decoded char
				;No checksum taken
	lhld	nxtadr		;Next out buffer posn
	mov	m,a		;Store char returned, may be EOF char
	inx	h
	jmp	buflp
;
full:
	xra	a		;Ensure Z
	ret			;Return on full buffer
;
;
;			Get next decoded character
;
getnxt:	lda	rcnt		;see if in the middle of
	ora	a		;repeat sequence...
	jz	norpt
	dcr	a		;Yes - reduce repeat remaining 
	sta	rcnt
	lda	last		;Get latest char again
	cmp	a
	ret			;Return with Z for ok
norpt:	call	decode
	rnz			;EOF? <A>=1AH
	cpi	dle		;Run encoding flag?
	jnz	norun
;			Handle DLE
	call	decode		;get count
	rnz			;EOF? (is really error after DLE)
	ora	a
	jnz	run		;Non-zero, real run 
	mvi	a,dle		;dle is encoded as dle,0
	cmp	a
	ret
;			;Run encoding found
run:	dcr	a		;Allow for char already retnd
	dcr	a		; & this one
	sta	rcnt		;Keep count yet to be retd
	lda	last		;return second time
	cmp	a
	ret
;			;Normal char, no run active 
norun:	sta	last		;This may be the start
	cmp	a
	ret
;
;
;			Read bits and decode to char
;			 note this version uses 3 bytes per node
;			 not 4.
;			 The first byte in each node is a flag byte
;			  .... x... - left node contains EOF marker
;			  .... .x.. - right node contains EOF marker
;			  .... ..x. - left node contains char
;			  .... ...x - right node contains char
;
decode:	lxi	d,0		;Set to node zero in table
	lda	bitbuf		;Get bits from bit buffer
	mov	c,a
bitlp:	lda	bitlft		;Any bits remaining? 
	ora	a
	jnz	nxtbit		;Yes - go use
	push	d
	call	getc		;No - replenish bit buffer
	jnz	badr		;Unexpected eof
	pop	d
	mov	c,a
	mvi	a,8		;Set as 8 bits inbuffer 
nxtbit:	dcr	a
	sta	bitlft		;Save no of bit remaining 
	lxi	h,SQTREE	;Set to node 0, left child ptr
	dad	d
	dad	d
	dad	d		;Add in node no (4 bytes/node)
	mov	b,m		;Get flag byte
	inx	h		;Step to left child pointer
	mov	a,c		;Get input bits 
	rrc			;Shuffle LOW-ORDER bit to Carry
	mov	c,a
	mov	a,b		;Get flag byte 
	jnc	getn3		;Zero input bit,leave at left
	inx	h		;add 1 to point to right child pointer
	add	b		;Normalize wanted flags to .... x.x.
getn3:
	mov	e,m		;Pick up child or char
;				<D> should always remain zero 
	ani	1010B		;Mask unwanted bits
	jz	bitlp		;Reg child pointer
;			Got to char or eof
	ani	1000B		;End of file marker?
	jnz	goteof		;Yes - get out with eof
	mov	a,c
	sta	bitbuf		;Save bit buffer
	mov	a,e		;Get decoded char (neg)
	ret
;
;			Exit on reg eof
goteof:
	mvi	a,eof
	ora	a
	ret
;
;			;Get input word (lo/hi, unencoded)
getw:	call	getc
	jnz	badr		;Unexpected eof
	push	psw
	call	getc
	jnz	badr		;Unexpected eof
	mov	h,a
	pop	psw
	mov	l,a
	ret
;
erext:
badr:	call	CDISP
	db	cr,lf,'Unexpected EOF on squeezed file',cr,lf,0
	jmp	EXIT
;
;			Get single (unencoded) char
getc:	lhld	inbufu
	xchg
	lhld	inbufs
	call	cmphlde		;End of input buffer?
	jz	getrf		;Yes
getc1:
	mov	a,m		;No get next byte
	inx	h
	shld	inbufs		;Save addr of next byte
	cmp	a
	ret
;
;			Refill input buffer
;
getrf:
	lda	SQEOF		;Is there anything else?
	ora	a
	jz	getok
	call	CDISP
	db	cr,lf,'Read past EOF on SQ file',cr,lf,0
	jmp	EXIT
getok:
	lhld	SECCNT		;Save sector count (decoded buffer only)
	push	h
	lxi	h,SQBUF		;Set input buffer as empty,
	shld	inbufs		;_and start of buffer
	xchg			;DE> buffer, next sector locn
	lhld	SQBUFE		;End of input buffer
	shld	inbufu		;Assume no end of file for now
	mov	a,l
	sub	e
	mov	l,a
	mov	a,h
	sbb	d		;Calc buffer size
	mov	h,a
	dad	h		;Convert to no of sectors
	mov	b,h		;No of sectors to read
;				# sectors limited to 100 max (<B>=0)
	lhld	FCBCRR		;No of 1st sector to read
	shld	SQBSC1
	call	FILBU1		;Read sector into SQBUF
;				<B> no of sectors not read if eof
;				HL> 128
;				DE> last sector read, or after if eof
	lhld	FCBCRR		;Get next SQ sector no
	shld	NXTSQS
	mov	a,b		;Did we fill buffer?
	ora	a
	jz	getrf2		;yes - no eof
	xchg			;Eof, adjust buffer end marker
	shld	inbufu		;Mark end of buffer used
	sta	SQEOF		;& flag eof
;
;			Input buffer re-filled
getrf2:
	pop	h
	shld	SECCNT		;Restore sector count (decoded buffer only)
	lhld	inbufu		;Get end of buffer
	xchg
	lhld	inbufs		;Get start of buffer
	call	cmphlde		;Something there?
	jc	getc1		;Yes - go for char
	jmp	erext		;No - read past eof or empty file
;
;end of baseline USQ code
;
otbufe:	dw	0		;End of decoded char buffer
inbufs:	dw	0		;Start of input buffer
inbufu:	dw	0		;End of used part input buffer
SQBUFE:	dw	0		;End of input buffer
;
nxtadr:	dw	DSKBUF		;Next byte in output buffer 
				; also used when loading tree
bitlft:	ds	1		;No of bits left in bit buffer
rcnt:	ds	1		;Run count remaining (DLE)
filchks:ds	2		;Checksum read from file
last:	ds	1		;Last reg char decoded
bitbuf:	ds	1		;Latest 8 bits (encoded) from input file
numvals:ds	2		;No of nodes in encodng tree
;
	ENDIF
;
;	Memory allocation
;
SECCNT:	DW	0		;number of sectors read into buffer
LINMAX:	DB	SCROLN		;number of to write lines on console
CHRMAX:	DB	MAXCHR-1	;number of characters to display per line
CHRMIN:	DB	0		;character to start displaying on line
CHRCNT:	DS	1		;character number in line
LINCNT:	DS	1		;line number on write or move back in buffer
TOPBUF:	DB	0		;Top of file is now in buffer
;				 Z - yes, NZ - no
;
	IF	SQUEEZE
;
NXTSEC:	DW	0		;Next (unsqueezed) sector not yet in BSKBUF
;				 set (and used) only by FILSQ
SQFLG:	DB	0		;File is squeezed
SQEOF:	DB	0		;End of file on squeezed file
SQREWD:	DB	0		;Flag the SQ input file is being re-read
;				 buffer refill rtn (getrf) to set inbufs
;				 as per offset in SQBYT, and pre-load
;				 bit buffer. Bit buffer to be adj
;				 as per Bitlft
SQBYT:	DW	0		;Offset of first data byte in SQ buffer
SQBSC1:	DW	0		;No of 1st sector in SQ buffer
NXTSQS:	DW	0		;No of last sector in SQ buffer
;
	ENDIF
;
	DS	60		;stack area
STACK:	DS	2		;old stack saved here
DSKBUF:	EQU	$		;disk buffer area above the program
;
ENDBUF	EQU	DSKBUF+MAXSEC*128
;
	IF	SQUEEZE
;
SQTREE	EQU	ENDBUF		;Space for SQ decoding tree
SQMAP	EQU	SQTREE+257*3
;				Space for SQ buffer mapping table
;				contains sq sect #, sq byte & bit offset
;				for every time DSKBUF was filled
;				1st entry contains index to latest mapping
;				triplet
;				To handle run compr straddling buffer end,
;				should also store rcnt & last 
SQBUF	EQU	SQMAP+100*4	;(allows for 100 8k buffers)
;				Input (squeezed) buffer
;				Runs up to top of free mem 
	ENDIF
;
	END	TPA
