home *** CD-ROM | disk | FTP | other *** search
- ;
- ; title 'BISHOW v3.02 - buffered bidirectional file scroll utility'
- ;
- ; Ver 3.02, 3 Nov 85, Rod Clark, Seattle WA
- ; - added Wordstar cursor pad (^C now = page down).
- ; - ESC exits, clears screen. Q exits, leaves screen.
- ; - Wrong keys are ignored. H = brief help. ? = help.
- ; - SHORT + SQUEEZE + LIBRARY = .COM file < 2k.
- ; - SHORT, no SQUEEZE, no LIBRARY = .COM file < 1k.
- ; - SHORT disables setting each margin interactively
- ; (the command line still sets the right margin and
- ; the page length), but it does let you scroll back
- ; and forth horizontally by tab stops within a file.
- ; The SHORT version gives two sets of cursor keys
- ; (Wordstar and CR/SP etc), but no help display.
- ; - BISHOW (no filename) tells whether it works on .LBR
- ; or squeezed files, or both, or just on plain files.
- ; - and fixed jumbled multiple-line .LBR directory.
- ;
- ; Ver 3.01, 15 Jan 84, Frans van Duinen, Toronto, Ont
- ; - made unsqueeze message optional
- ; - added library capability
- ; - fixed bug in conditional assembly of CLRSCR
- ;
- ; 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
- ;
- ; Ver 1.07, 1 Aug 83, Ted H. Emigh ...!unc!tucc!emigh
- ; - added screen width specification
- ; - added screen definition commands (see notes below)
- ;
- ; Ver 1.06, 2 Jul 83, Chuck Forsberg
- ; - added commands for more, mince, vi familiarity.
- ; Bad cmd gives help
- ;
- ; Ver 1.051, 26 June 83, Dick Mead
- ; - added "?" for help on commands.
- ;
- ; Ver 1.05, 31 May 83, Bruce Ratoff
- ; - added 'N' (next line) and 'P' (previous line) cmds
- ; - decreased buffer from 8k to 4k (8k takes too long)
- ;
- ; Ver 1.04, 15 May 83, Keith Petersen, W8SDZ
- ; - fixed bug which caused display past end-of-file
- ; and added bogus eof in case none at file end
- ; - added strip of high-order bit in line count routine
- ; - added exit clear of any left-over keyboard character
- ;
- ; Ver 1.03, 11 May 83, Keith Petersen, W8SDZ
- ; - fixed to allow assembly with ASM.COM
- ; - fixed screen clear bug when crossing read boundries
- ; - added strip for high-order bit in character before
- ; printing (needed for WordStar files)
- ; - improved stack routines
- ; - fixed bug in console input routine
- ; - removed Z80 dependant code (now works on 8080 too)
- ;
- ; Ver 1.02, 06 May 83, Lucien Pan, Toronto, Canada
- ; - fixed some minor bugs
- ; - returns to ccp w/o warm boot
- ; - filters form-feeds (useful in .PRN files)
- ; - scrolls foward/backwards by same number of lines
- ; - disable/enable cursor during scroll for H-19
- ;
- ; Ver 1.01, 30 Mar 83 - added BDOS function 6. W.F.Mcgee
- ;
- ; Ver 1.00, 23 Aug 82 Phil Cary, 748 Kenilworth Parkway, Baton
- ; Rouge, LA 70808
- ;
- ; 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.
- ;
- ; This bidirectional version 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. 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.
- ;
- ;Define version number for help message
- ;
- VERS EQU 3 ;Note current use in DB constrains VERS &
- REVS EQU 02 ; REVS to be one and two digits respectively
- ;
- FALSE EQU 0
- TRUE EQU NOT FALSE
- ;
- ; ASCII equates
- ;
- ENDMSG EQU 0 ;null
- BS EQU 8 ;Backspace
- TAB EQU 9 ;tab
- LF EQU 0AH ;line feed
- FEED EQU 0CH ;form feed
- CR EQU 0DH ;carriage return
- EOF EQU 1AH ;end of file
- ESC EQU 1BH ;escape
- SPACE EQU 20H ;space
- ;
- ;------------------------------------------------------------------------------
- ; @@@@@
- ; ///////////////////// User settings ///////////////////////
- ;
- HEATH EQU FALSE ;assemble for H-19 terminal
- OSBORNE EQU FALSE ;assemble for 52-column screen
- ;
- SHORT EQU TRUE ;no SQ or LBR = 1k / with SQ and LBR = 2k
- LONG EQU NOT SHORT ;duplicate keys, includes help, margin set
-
- SQUEEZE EQU TRUE ;Optional, to handle squeezed files
- LIBRARY EQU TRUE ;Optional, to handle .LBR files
- ;
- NOWAIT EQU TRUE ;true = no wait after screen clear
- SILENT EQU TRUE ;true = no superfluous "unsqueezing text" msg
- ;
- IF NOT OSBORNE
- SCROLN EQU 24 ;number of lines per scroll
- MAXCHR EQU 79 ;number of characters per line
- ENDIF
- ;
- IF OSBORNE
- SCROLN EQU 24 ;number of lines per scroll
- MAXCHR EQU 51 ;number of characters per line
- ENDIF
- ;
- ; ///////// change the help tables if you change keys //////////
- ;
- ; command keys - short version
- ;
- LINE EQU 'X'-40H
- LINE2 EQU CR
- PAGE EQU 'C'-40H
- PAGE2 EQU SPACE
- LINEUP EQU 'E'-40H
- LINEUP2 EQU 'P'
- PAGEUP EQU 'R'-40H
- PAGEUP2 EQU 'B'
- ARWLFT EQU 'S'-40H
- ARWLFT2 EQU 'H'-40H
- ARWRT EQU 'D'-40H
- ARWRT2 EQU TAB
- TOP EQU 'T'
- TOP2 EQU '1'
- QUIT EQU 'Q'
- QUITCL EQU ESC
- ;
- ; additional command keys - long version
- ;
- IF LONG
- LINE3 EQU LF
- LINE4 EQU '+'
- LINE5 EQU 'Z'-40H
- LINE6 EQU 'N'
- PAGE3 EQU 'F'
- PAGE4 EQU 'F'-40H
- PAGE5 EQU 'V'-40H
- LINEUP3 EQU 'K'-40H
- LINEUP4 EQU '-'
- LINEUP5 EQU 'W'-40H
- PAGEUP3 EQU 'B'-40H
- ARWLFT3 EQU 'A'-40H
- ARWRT3 EQU 'L'-40H
- SETKEY EQU 'S'
- HUH EQU 'H'
- HUH2 EQU '?'
- ENDIF
- ;
- ; ////// check help and clrscr routines at @@@@@ below ////////
- ;
- ;------------------------------------------------------------------------------
- ;
- 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
- ;
- ; Operational equates
- ;
- MAXSEC EQU 32 ;number of sectors in buffer
- SQSIGN EQU 0FF76H ;Signature for SQ files
- LBSIGN EQU 2000H ;Signature for library files
- DLE EQU 090H ;Char flag for run compression (SQ)
- ;
- ORG TPA
- ;
- JMP START ;skip over next subroutines
- ;
- ;------------------------------------------------------------------------------
- ; @@@@@
- ; ///////// change help tables to reflect key changes /////////
- ;
- IF LONG AND NOT OSBORNE
- HELP3:
- CALL CDISP
- DB CR,LF,LF
- DB ' ^E ^X ^R ^C T ^S ^D '
- DB ' S H Q',CR,LF
- DB 'up line next line up page next page top left right'
- DB ' set help quit',CR,LF
- DB ' P - cr + B F sp 1 bs tab '
- DB ' S ? ESC',CR,LF
- DB ' ^W ^K ^Z lf N ^B ^F ^V ^A ^L',CR,LF
- DB ENDMSG
- JMP GETCMD
- ENDIF
- ;
- IF LONG AND OSBORNE
- HELP3: JMP HELP2
- ENDIF
- ;
- IF LONG AND NOT OSBORNE
- HELP2:
- CALL CDISP
- DB CR,LF,LF
- DB ' P ^E line up B ^R page up bs ^S left '
- DB ' S set Q quit',CR,LF
- DB ' cr ^X line sp ^C page tab ^D right'
- DB ' T 1 top ESC clear',CR,LF
- DB ENDMSG
- JMP GETCMD
- ENDIF
- ;
- IF LONG AND OSBORNE
- HELP2:
- CALL CDISP
- DB CR,LF,LF
- DB '^E line up ^R page up ^S left T top Q quit',CR,LF
- DB '^X line ^C page ^D right S set ESC clear',CR,LF
- DB ENDMSG
- JMP GETCMD
- ENDIF
- ;
- ; ////////////////// check your clear code ///////////////////
- ;
- CLRSCR:
- CALL CDISP ;command to erase screen and home cursor
- ;
- IF NOT (HEATH OR OSBORNE)
- DB ESC,'+',ENDMSG ;put your screen clear string here
- ENDIF
- ;
- IF HEATH
- DB ESC,'E',ENDMSG ;for H/Z-19 terminal -- Change as required
- ENDIF
- ;
- IF OSBORNE
- DB 1AH,ENDMSG ;for Osborne (& Televideo?)
- ENDIF
- ;
- ; /////////////////// end of user settings ////////////////////
- ;
- ;------------------------------------------------------------------------------
- ;
- IF NOT NOWAIT
- WAIT: MVI B,0 ;waste time (may or may not be necessary)
- WAIT1: XTHL ;good time gobbeler!
- XTHL
- DCR B
- JNZ WAIT1
- ENDIF
- ;
- RET ;return from clrscr
- ;
- START:
- IF HEATH
- CALL CDISP
- DB ESC,'x5',ENDMSG ;disable cursor
- ENDIF
- ;
- LXI H,0 ;get ccp's stack
- DAD SP
- SHLD STACK ;save old stack for reinstatement at exit
- 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
- ;
- CALL EATSP ;Step to next non-bl in input
- JZ OPENF ;no more characters
- ;
- CALL FILNAM ;Skip file name, returns <B>=0 or <A>=20H
- JZ OPENF ;only file name in tail
- ;
- ; Check if there is a member name
- CALL EATSP ;Step to next non-bl in input
- JZ OPENF ;no more characters
- CPI '9'+1 ;Numeric?
- ;
- IF LIBRARY
- JNC MEMB ;No -
- ENDIF
- ;
- CPI '0'
- JNC NUMBER ;Yes - must be width & height
- ;
- ;
- IF LIBRARY ;Have member name (at FCB+11H)
- MEMB:
- STA MEMNAM ;No - have member name
- PUSH H ;Posn in command line
- PUSH B ;# of chars remaining
- LXI H,FCB+11H ;Source
- LXI D,MEMFCB+1 ;Destination
- MVI B,11 ;Move name + type
- CALL MOVE
- ; add LBR suffix if required
- LXI H,FCB+9 ;Is there a suffix
- MOV A,M
- CPI SPACE
- JNZ NUMBR2 ;Yes - leave
- MVI M,'L'
- INX H
- MVI M,'B'
- INX H
- MVI M,'R'
- NUMBR2:
- POP B
- POP H
- CALL FILNAM ;Skip member name, returns <B>=0 or <A>=20H
- JZ OPENF ;end
- ENDIF ;above section included in library ver. only
- ;
- ; Handle screen width & height
- NUMBER:
- 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
- ;
- IF SQUEEZE
- CALL CHKSQ ;Check for squeezed, init if
- ENDIF ;Returns first word in file in <HL>
- ;
- IF LIBRARY
- CALL FILBF0 ;fill the disk buffer with start of file
- CALL CHKLB ;Check for library file
- CALL CLRSCR
- JMP WRTFW0 ;Buffer contains top sectors
- ENDIF
- ;
- WRTFWD:
- CALL CLRSCR ;erase the screen
- CALL FILBF0 ;fill the disk buffer with start of file
- WRTFW0:
- 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 FEED ;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)
- JC WRTFW1 ;continue with next character
- CALL FILBUF ;fill the disk buffer with next sectors
- JMP WRTFW0 ;start over
- ;
- HELP: CALL CDISP
- DB CR,LF,'BISHOW '
- DB (VERS MOD 10)+'0','.'
- DB REVS/10+'0',(REVS MOD 10)+'0',CR,LF
- ;
- IF LIBRARY AND SQUEEZE
- DB 'bishow d:ANYsqFIL.lbr '
- ENDIF
- ;
- IF LIBRARY AND NOT SQUEEZE
- DB 'bishow a:FILnotSQ.lbr '
- ENDIF
- ;
- IF SQUEEZE AND NOT LIBRARY
- DB 'bishow a:SQZorNOT.fil '
- ENDIF
- ;
- IF (NOT SQUEEZE) AND (NOT LIBRARY)
- DB 'bishow d:anyPLAIN.fil '
- ENDIF
- ;
- IF LIBRARY
- DB '[member] '
- ENDIF
- ;
- DB '[cols [lines]]',CR,LF,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
- ;
- GETCM1: CALL GETIN ;Get input char if any
- 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:
- ; /////////////// commands for short version /////////////////
- ;
- CPI LINE ;scroll next line
- JZ WRTNXT
- CPI LINE2
- JZ WRTNXT
- CPI PAGE ;scroll next page
- JZ WRTFW1
- CPI PAGE2
- JZ WRTFW1
- CPI LINEUP ;scroll prev line
- JZ WRTPRV
- CPI LINEUP2
- JZ WRTPRV
- CPI PAGEUP ;scroll page backward
- JZ WRTBAK
- CPI PAGEUP2
- JZ WRTBAK
- CPI ARWLFT ;scroll left
- JZ ADJMM
- CPI ARWLFT2
- JZ ADJMM
- CPI ARWRT ;scroll right
- JZ ADJMM
- CPI ARWRT2
- JZ ADJMM
- CPI TOP ;go to 1st line of file
- JZ WRTTOP
- CPI TOP2
- JZ WRTTOP
- CPI QUIT ;does not clear screen
- JZ EXIT
- CPI QUITCL ;clears screen
- JZ EXITCL
- ;
- ; //////////////// commands for long version /////////////////
- ;
- IF LONG
- ;
- CPI LINE3
- JZ WRTNXT
- CPI LINE4
- JZ WRTNXT
- CPI LINE5
- JZ WRTNXT
- CPI LINE6
- JZ WRTNXT
- ;
- CPI PAGE3
- JZ WRTFW1
- CPI PAGE4
- JZ WRTFW1
- CPI PAGE5
- JZ WRTFW1
- ;
- CPI LINEUP3
- JZ WRTPRV
- CPI LINEUP4
- JZ WRTPRV
- CPI LINEUP5
- JZ WRTPRV
- ;
- CPI PAGEUP3
- JZ WRTBAK
- ;
- CPI ARWLFT3
- JZ ADJMM
- ;
- CPI ARWRT3
- JZ ADJMM
- ;
- CPI SETKEY
- JZ SETSCR
- ;
- CPI HUH
- JZ HELP2 ;brief table of commands
- CPI HUH2
- JZ HELP3 ;full table of commands
- ;
- ENDIF
- ;
- JMP GETCMD
- ;
- ;
- ; 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 WRTFW0 ;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 FEED ;__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 with top of file
- FILBF0:
- 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 ;Reset to sector zero
- ;
- IF NOT LIBRARY
- STA FCBCRR+1 ;
- STA FCBCRR+2 ;__and clear the overflow
- ENDIF
- ;
- IF LIBRARY
- LHLD SCZERO ;Set to sector zero for file/member
- SHLD FCBCRR
- ENDIF
- ;
- ; ;Fill buffer from spec'd sector
- FILBUF:
- MVI B,MAXSEC ;number of sectors to resd
- FILB1S:
- ;
- IF LIBRARY
- LHLD SCZERO ;Get top sector for member
- XCHG
- LHLD FCBCRR ;Is this top of file?
- CALL cmphlde ;This it? (<A>=0 if equal)
- ENDIF
- ;
- IF NOT LIBRARY
- LHLD FCBCRR ;Is this top of file?
- MOV A,H
- ORA L
- ENDIF
- ;
- STA TOPBUF ;Set top of file in buffer flag
- LXI D,DSKBUF ;load start of disk buffer
- LXI H,0 ;zero out the
- SHLD SECCNT ;__number of sectors in buffer
- ; ; 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
- ;
- IF LIBRARY
- PUSH D ;Save sector buffer pointer
- LHLD FCBCRR ;get current record number
- XCHG
- LHLD SCLAST ;& get last sector for member (or FFFF)
- CALL cmphlde ;Are we within member
- POP D
- JC RDERR ;no, last sector read
- ENDIF
- ;
- 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,'Disjoint sectors',CR,LF,0
- JMP EXIT ;Should never happen
- USQBAK: ;Going backward
- ENDIF
- ;
- IF SQUEEZE AND LIBRARY
- LHLD SCZERO ;Get 1st sector for member
- CALL cmphlde ;All the way back to start?
- ENDIF
- ;
- IF SQUEEZE AND NOT LIBRARY
- MOV A,D ;All the way?
- ORA E
- ENDIF
- ;
- IF SQUEEZE
- 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
- ENDIF
- ;
- IF SQUEEZE AND NOT SILENT
- CALL CDISP ;Show msg where is
- DB '>>> Unsqueezing Text <<<',ENDMSG
- ;Corrupts display if after CR but before LF
- ENDIF
- ;
- IF SQUEEZE
- CALL FILUSQ ;fills unsq buffer
- ENDIF ;SQEOF set as well then
- ;
- IF SQUEEZE AND NOT SILENT
- CALL CDISP ;Remove msg just displayed, assumes
- ;BS works 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
- ENDIF
- ;
- IF SQUEEZE
- 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 'No File',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
- ;
- IF LONG
- 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
- DCX H ;delete leading zeroes
- DCX H ;__in the number
- MVI C,SPACE ;__and replace with spaces
- MOV A,B
- CMP M ;check first digit for '0'
- JNZ CDISP ;not zero
- MOV M,C ;replace with space
- INX H
- CMP M ;check second digit for '0'
- JNZ CDISP ;not zero
- MOV M,C ;replace with space
- ENDIF
- ;
- 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
- MOV E,A ;set up character
- MVI C,CONOUT ;__to send to console
- CALL BDOS ;do it
- POP PSW
- CO5: POP H ;restore
- POP D ;__the registers
- POP B
- RET
- ;
- CO1: PUSH B ;Save the registers
- PUSH D
- PUSH H
- MOV E,A
- 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 CO2
- LDA CHRMAX ;get maximum characters per line
- CMP M ;see if too many char
- JC CO5 ;don't print character
- MOV A,E ;restore and print character
- CPI TAB ;fix chrcnt for tabs
- JZ TABFIX
- INR M ;increment character count
- 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 CO2 ;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
- ;
- ;
- IF LONG
- 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,'Max 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,'Min 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 per Page: '
- ;
- 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
- ;
- ENDIF ;above code (flying set) only if long
- ;
- ADJMM: ;Adjust char min/max on cursor left/rt
- PUSH H
- CPI ARWLFT ;Move left (decrease)?
- JZ ADJM1 ; set flag
- CPI ARWLFT2
- JZ ADJM1
- ;
- IF LONG
- CPI ARWLFT3
- JZ ADJM1
- ENDIF
- ;
- ADJM1: LDA CHRMAX ;rightmost char to display
- MOV H,A
- LDA CHRMIN ;leftmost char to display
- MVI L,8 ;Scroll by 8
- JZ ADJMMD ;OK - adjust to left
- ADD L ;No - increase min, no limit
- PUSH PSW
- MOV A,L
- ADD H ;increase max
- JMP ADJMMS ;OK - adjust to right
- ADJMMD:
- SUB L ;adjust to left
- PUSH PSW
- MOV A,H
- SUB L
- ADJMMS: ;adjust to right
- MOV H,A ;<H> max
- POP PSW ;<A> min
- CMP H ;Wrap, (max< min)
- JNC ADJMMX ;OK - leave unchanged
- STA CHRMIN
- MOV A,H
- STA CHRMAX
- ADJMMX:
- POP H
- LDA LINMAX ;write the same screen
- JMP WRTBK0 ;same effect as WRTSAM above
- ;
- ;
- IF LONG
- 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
- ;
- ENDIF
- ;
- EXITCL:
- ; Clear screen only on <ESC> exit
- CALL CLRSCR ;clear the screen
- ;
- EXIT:
- ; CALL GETIN ;__get any waiting character
- ; CALL GETIN ;and a possible second character
- ;
- IF HEATH
- CALL CDISP ;re-enable cursor
- DB ESC,'y5',ENDMSG
- ENDIF
- ;
- LXI D,FCB ;close file
- MVI C,CLOSE ;--in case this is MP/M
- CALL BDOS
- ;
- EXIT1:
- LHLD STACK ;get old stack
- SPHL
- RET ;return to CCP
- ;
- ;
- IF LIBRARY
- CHKLB: ;Check for Library file
- xra a
- sta memfcb
- sta lbflg ;Clear library flag
- LHLD DSKBUF ;Get 1st word in file
- lxi d,lbsign ;Get expected value
- call cmphlde
- jz islb
- ; Not library
- ;
- lda memnam ;Was member specified
- ora a
- rz ;No - ok
- call CDISP
- db cr,lf,'Not LBR',cr,lf,0
- jmp EXIT ;Get out to leave msg visible
- ;
- ; Is library
- islb:
- mvi a,1
- sta LBFLG ;Yes - set library flag
- LXI H,DSKBUF+14 ;Set to dir size (in sectors)
- mov a,m ;Assume <255 entries
- RAL
- RAL ;Convert # sectors to # entries
- DCR A ;Less 1 for file descriptor
- sta dirsiz ;directory size in entries
- mov b,a ;Save no of entries for loop
- LXI H,DSKBUF+20H ;Set 1st member entry
-
- CALL CDISP ;write a blank line before first dir line
- DB CR,LF,0
- ;
- ; Loop through directory entries
- dirlp:
- push b ;Save no of entries remaining
- MOV A,M ;Get entry status
- ORA A ;Deleted?
- JNZ nyet ;Yes - skp to next
- LDA MEMNAM ;Do we have member name on command line?
- ORA A
- JZ DISPM ;No - display member name routine
- ;
- ; See if this is the requested member
- ;
- mvi b,12 ;Length of names + 00H in front
- lxi d,memfcb
- call cpstr ;Compare names
- jz found
- jmp nyet
- ;
- ; Display rather than look for the member
- ;
- DISPM: mvi b,11 ;Length of names
- push h
- inx h ;Step to actual name
- DSPMLP:
- mov a,m
- call CO ;Display one char
- inx h
- dcr b ;Reduce count remaining
- jz nmend ;end of name
- ;
- ENDIF
- ;
- IF LIBRARY AND NOT OSBORNE
- ; (Bypass for Ozzys narrow screen)
- mov a,b
- cpi 3 ;only 3 more?
- jnz DSPMLP ;No -
- mvi a,'.' ;Yes - put out dot
- call CO
- ;
- ENDIF
- ;
- IF LIBRARY
- jmp DSPMLP ;Go for next char
- ;
- ;Have now displayed member name
- nmend:
- ; In later versions multiple across
- lxi h,namexc ;Max no of names across sofar
- mov a,m
- inx h ;Step to names across sofar
- inr m ;Count current
- cmp m ;Over max?
- jnc notmax ;not yet
- mvi m,0 ;Yes - reset
- call CDISP
- DB CR,LF,0
- jmp nyet1
- notmax:
- call CDISP
- ENDIF
-
- IF LIBRARY AND NOT OSBORNE
- DB ' '
- ENDIF
-
- IF LIBRARY
- DB '| ',0
- nyet1:
- POP H ;Reset to start of this entry
- ;
- nyet:
- lxi b,20h ;Length of each entry
- dad b ;Step to next
- pop b ;Get entry count (remaining)
- dcr b
- jnz dirlp ;More members
- LDA MEMNAM ;Do we have member name on command line?
- ORA A
- JZ EXIT ;if not, we have shown dir, now exit
- call CDISP
- db 'Not in LBR',cr,lf,0
- jmp EXIT ;and show the poor schmuck the directory
- ;
- ; Found the member name
- found:
- pop b ;Clear stack
- lxi d,12
- dad d
- push h ;save pointer for now,
- inx h ;point to size
- inx h
- mov a,m ;get low byte
- inx h
- mov h,m
- mov l,a
- ora h ;if a=0 then file is 0k
- jz nullen ;go complain
- xthl ;get pointer back, save size
- mov a,m ;get file address
- inx h
- mov h,m
- mov l,a
- SHLD SCZERO ;Save as first file sector
- POP D ; & get size back
- DAD D ;Convert to last sector no (inclusive)
- SHLD SCLAST
- ENDIF
- ;
- IF LIBRARY AND SQUEEZE
- LDA SQFLG ;Get SQ flag in case of double squeeze
- ORA A
- JZ NOLBSQ ;Ok, library itself not squeezed
- CALL CDISP
- DB 'unSQ LBR',CR,LF,0
- JMP EXIT
- NOLBSQ:
- CALL CHKSQ ;Check if member squeezed
- ENDIF
- ;
- IF LIBRARY
- CALL FILBF0 ;Refill buffer, now for member
- ; (FILBUF handles member offset in library)
- ret
- ;
- ; ;Member is empty
- nullen:
- CALL CDISP
- DB 'Empty',CR,LF,0
- JMP EXIT
- ENDIF
- ;
- ; Get input if any
- GETIN:
- MVI C,6 ;direct console I/O
- MVI E,0FFH ;__set up for input
- CALL BDOS ;Get char
- RET
- ;
- ; Compare strings HL> to DE> over <B>
- ; <DE> and <B> are changed, <HL> kept
- cpstr:
- push h
- cp$lp:
- ldax d
- cmp m
- jnz cp$ex ;No match
- inx d
- inx h
- dcr b
- jnz cp$lp
- cp$ex:
- pop h
- ret
- ;
- ; Compare <HL> to <DE>
- ; Z - equal; C - <HL> less than <DE>
- ; if equal returns <A>=0
- cmphlde:
- mov a,h
- sub d
- rnz
- mov a,l
- sub e
- ret
- ;
- ; Skip blanks in input
- ;
- EATSP: MOV A,M ;get character if there is one
- INX H
- DCR B ;b=number of characters left
- RZ ;no more characters
- CPI SPACE ;ignore spaces
- JZ EATSP
- DCX H ;Step back to 1st non-blank
- INR B
- ORA A ;Force NZ
- RET
- ;
- ; Skip name in input
- ;
- FILNAM: MOV A,M ;get characters in file name
- INX H
- DCR B ;b=number of characters left
- RZ ;only file name in tail
- CPI SPACE ;wait for next space
- JNZ FILNAM
- ORA A ;Force NZ
- RET ;Blank
- ;
- ; Move from HL> to DE> over <B>
- ;
- MOVE:
- MOV A,M
- STAX D
- INX H ;Step to next source
- INX D ; & destination
- DCR B ;Reduce count (00=256)
- JNZ MOVE
- 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
- sta FCBCRR+2 ; and overflow
- shld numvals ;Clear # nodes
- ENDIF
- ;
- IF SQUEEZE AND LIBRARY
- LHLD SCZERO ;Get 1st sector for member
- SHLD NXTSEC ;& save as next sector
- ENDIF
- ;
- IF SQUEEZE
- shld FCBCRR ;Clear next record
- 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
- ; Read and validate signature word
- call getw ;Read 1st word in file
- lxi d,sqsign ;Get expected value
- call cmphlde
- rnz
- mvi a,1
- 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,'Bad SQ tree',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 & 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,'EOF?',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,'EOF',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 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
- ;
- ;
- IF LIBRARY
- namexc: db (MAXCHR/14)-1 ;No of directory names across display
- db 0 ;No of names so far
- dirsiz: db 0 ;# of members possible in directory
- memnam db 0 ;Member name specified on command line
- SCZERO: DW 0 ;First sector for member
- SCLAST: DW 0FFFFH ;Last sector for member (included in member)
- ; SCZERO and SCLAST are relative in file
- LBFLG: DB 0 ;File is a library file
- memfcb: DS 12 ;Member name here
- 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+256*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