.xlist ;Short .PRN file for Z8E ;--------------------------------------------------------------------- ; ; TYPEQZ v1.0 ; 23 Aug 1986 ; ; John Hastwell-Batten ; Tesseract RCPM+ ; Dural, NSW, Australia ; ;--------------------------------------------------------------------- ; ; TYPEQZ is a multi-file unsqueezing/uncrunching TYPE utility for ; both RCPM and normal use. It is intended to replace the TYPE ; command in the CP/M CCP. ; ; TYPEQZ accepts multiple ambiguous file names as arguments and ; lists on the console the contents of the files matching those ; arguments. ; ; E.g. TYPEQZ *.A?M B5:E??.C 3:*.C? ; ; There is no intrinsic .LBR or .ARC file access. It is this ; author's contention that such is unnecessary with utilities such ; as LUX and LD available and that the multi-file convenience far ; outweighs any disadvantage arising therefrom. ; ; TYPEQZ will not list non-text files. Although TYPEQZ uses an ; exclusion list to help it decide what is and is not typeable, it ; is not dependent on that exclusion list. For example, you can ; omit .CMD files from the exclusion list. TYPEQZ will decide ; whether the .CMD file is typeable (as in the case of dBASE II ; program files) or whether it is binary rubbish (as in the case ; of CP/M-86 executable code). TYPEQZ will not send any control ; characters to the screen; it is terminal-independent and safe ; for RCPM use. ; ; If running under BYE5 and the "wheel" byte is not set, TYPEQZ ; will not type files with the "SYS" attribute (T2) set and it will ; also restrict the range of disks and user areas to those allowed ; by BYE5/ZCPR/ZCMD/CCP+. It will also ignore the file line limit. ; ; Enhanced video functions can be enabled for local operation or in ; a BYE5 environment. Video controls are not sent over the phone ; link. ; ; There are no conditional assembly switches. All configuration ; can be done by patching the object code. ; ;--------------------------------------------------------------------- ; ; Credits: ; ; 1. This program is possible because of Steven Greenberg's ; work on unscrambling LZW-encoded ("crunched") files. ; ; 2. The MFNAME: routine was adapted from CRC64.ASM. ; ; 3. Some details of calling Steven Greenberg's "uncrunch" ; routine were taken from Steven's TYPELZ20.Z80. ; ; All other code is the original work of the author and any ; similarity to code in other programs by other persons is purely ; accidental (or a function of similar thinking). Apart from the ; items listed above no code has been plagiarised from any other ; program. ; ;--------------------------------------------------------------------- ; ; HISTORY: ; ; 1.7 16 Dec 86 John Hastwell-Batten ; ; - Extended list of 'legal' characters in typeable files to ; include BS and BEL. ; ; - Pending a fix to USQREL, installed bypass for problem in that ; module which causes it to reject squeezed files with a zero in ; either CRC byte. ; ; (Both of the above were suggested by Steven Greenberg). ; ; 1.6 22 Oct 86 Tony Benham ; ; - Fixed an obscure bug. Stack pointer was not being saved for ; control-X exit until typeout actually commenced. The program ; would crash if the screen filled with "can't type" messages ; and then control-X were pressed. ; ; 1.5 15 Oct 86 John Hastwell-Batten ; ; - Made WHEEL byte address patchable for RCPM use (as suggested by ; Bob Freed). ; - Maximum drive/user values now determined in address-independent ; fashion when operating in RCPM/BYE5 environment. ; - Implemented patchable option for operation in RCPM environment ; without BYE5. ; ; 1.4 12 Oct 86 John Hastwell-Batten ; ; - Corrected user number restoration for CP/M 2.2. ; - Implemented memory-size checking - program will now stop if ; there isn't enough memory for it to run. ; ; (Thanks to Bob Freed for pointing out the bug and for several ; suggestions including the memory test.) ; ; 1.3 10 Oct 86 John Hastwell-Batten ; ; - Highlight video option to display filenames and messages. ; - Fixed bug in reporting of squeezed file name extensions. ; ; 1.2 07 Oct 86 John Hastwell-Batten ; ; - Optional line limit for RCPM use ; - Force control-X exit from file typeout to close the file ; (should keep MP/M happy) ; ; 1.1 06 Oct 86 John Hastwell-Batten ; ; Beta-test version installed on Tesseract RCPM+ ; ; - Made all internally-generated messages subject to control-S ; suspension and control-C abort. ; - Notify user of each command-line argument which does not match ; any file. ; ; 1.0 03 Oct 86 John Hastwell-Batten ; ; Alpha-test version installed on Tesseract RCPM+ ; ;--------------------------------------------------------------------- version equ 1 revision equ 7 entry getByt, out, $memry extrn uncrel, usqrel .request UNCREL, USQREL .Z80 aseg ;Makes using Z8E easier org 100h ;--- CP/M address equates --- ddma equ 80h ;Default dma address bdos equ 5h ;BDOS entry point fcb equ 5Ch fcbExt equ fcb+12 fcbRno equ fcb+32 EXTN equ 9 ;--- BDOS function equates --- CONIO equ 6 ;Direct console I/O PRTSTR equ 9 ;Print string CPMVSN equ 12 ;Get operating system version OPEN equ 15 ;Open file CLOSE equ 16 ;Close file SRCHF equ 17 ;Search for first matching file name SRCHN equ 18 ;Search for next matching file name READ equ 20 ;Read file (sequential) CURDSK equ 25 ;Return current disk SETDMA equ 26 ;Set DMA address SGUSER equ 32 ;Set/get user number LOCO equ 68 ;Output character to local console only MXDRV equ 69 ;Set/get maximum drive MXUSR equ 70 ;Set/get maximum user number ;--- Miscellaneous character equates --- ETX equ 03h ;^C CAN equ 18h ;^X DC3 equ 13h ;^S BEL equ 07h BS equ 08h CR equ 0Dh LF equ 0Ah HT equ 09h FF equ 0Ch DEL equ 7Fh CPMEOF equ 1Ah ;----------------------------------------------------------------------------- begin: jp start ;----------------------------------------------------------------------------- ; ; Patchable data items (Start at 103h) ; ;----------------------------------------------------------------------------- db 'Lines:' lines: db 24 ;Lines per screen ;----------------------------------------------------------------------------- db 'Cols:' cols: db 80 ;Columns without auto-wrap ;----------------------------------------------------------------------------- db 'MaxUsr:' maxUsr: db 15 ;Maximum user area ;----------------------------------------------------------------------------- db 'MaxDrv:' maxDrv: db 'H'-'@' ;Maximum disk drive ;----------------------------------------------------------------------------- db 'ccpPages:' ccpPages: db 8 ;Length of CCP (for CP/M 2.2 only) ;----------------------------------------------------------------------------- db 'BYE5:' ;BYE 5xx communications supervisor flag useBYE: ;Non-0 if not RCPM or if RCPM with BYE5 db 1 ;Set to 0 if running RCPM and not using BYE5 ;-------------------------------------------------------------===------------- db 'Limit:' lineLimit: dw 400 ;Max lines per file if restricted ;----------------------------------------------------------------------------- db 'WhlPtr:' wheel: dw 003Eh ;Address of wheel byte ;----------------------------------------------------------------------------- ; ; Highlight video sequences - first byte is length, then up to 7 bytes ; to effect the video change. If you don't want to use highlight video ; then simply set the length bytes to zero. ; SAFE FOR RCPM USE! Highlight sequences are not sent to the remote ; computer. ; ; Highlight sequence 1 is used for filename display ; Highlight sequence 2 is used for any error messages ; ; Recommendations: ; a) Monochrome screens: ; Highlight-1: Inverse video or high intensity video ; Highlight-2: Underlined or plain ; b) Colour screens: ; Highlight-1: Cyan or green ; Highlight-2: Red or magenta ; Normal: Yellow ; ;------------------------------------------------------------------ db 'Highlight-1:' hiVid1: db 4 ;Length of string to switch ON highlight db 1Ch,47h,42h,40h ;Datapoint 8227 sequence (GREEN) db 0,0,0 ;Patch space db 'Highlight-2:' hiVid2: db 4 db 1Ch,47h,41h,40h ;Datapoint 8227 sequence (RED) db 0,0,0 db 'Normal:' normVid: db 2 ;Length of string to switch OFF highlight db 1Bh,04h ;Datapoint 8227 sequence (NORMAL=YELLOW) db 0,0,0,0,0 ;Patch space ;----------------------------------------------------------------------------- ; ; Exclusion list. This is a list of file types which you do not ; want typed. ; ; Note that there are some file types which you should NOT put in ; here. For example, .CMD can be CP/M-86 executable code or it can ; be dBASE program source. TYPEQZ will automatically abort typeout ; of the CP/M-86 executable code but will allow typeout of the ; dBASE program source PROVIDED THAT YOU DON'T PUT 'CMD' IN HERE! ; ;----------------------------------------------------------------------------- defb 'Exclude:' exList: defb 'COM' ;CP/M-80 and MS-DOS executable code defb 'C0M' ;Renamed .COM defb 'OBJ' ;Renamed .COM defb 'SPR' ;MP/M and CP/M+ system files defb 'EXE' ;MS-DOS executable code defb 'LBR' ;Composite file defb 'ARC' ;Composite file defb 'OV?' ;Overlay files. .OVR, .OVL etc defb 'SYS' ;System file defb 'INT' ;Interpreted code file (CBASIC etc) defb 'REL' ;Relocatable object file defb '?RL' ;Other relocatable objects (PRL, CRL, IRL) defb 'RSX' ;Resident system extension defb 'RSP' ;Resident system procedure defb 0,0,0 ;Patch space defb 0,0,0 defb 0,0,0 defb 0,0,0 defb 0,0,0 defb 0 ; Table must always end with a zero ;============================================================================= ; ; Section 1 - Preliminaries ; ;============================================================================= start: ld a,7Fh ;Find out if z80 add a,a ;Cause overflow jp pe,Z80 ;Parity (overflow) flag set proves Z80 ld de,needZ80 ;Not a Z80 or equivalent - display pExit: ld c,PRTSTR ;Print message and exit with warm boot call bdos rst 0 bdosy: ;Convenient place to park a little routine push iy call bdos pop iy ret Z80: ld (ccpStk),sp ;Save CP/M stack (useful only on 2.2) ld sp,locStk ;Set local stack ld hl,($memry) ld de,255 add hl,de ;H now points at first page of free memory ld a,(bdos+2) ;Get upper limit of free memory sub h ;A now has free memory size in pages sub 96 ;Need at least 24K for UNCRUNCH routine ld de,tooSmall ;Point at error message jr c,pExit ;Exit now if not enough memory ld hl,ccpRet ;Point at 'CCP return' exit flag ld (hl),0 ;Clear it for now push hl ;Save exit flag pointer .. push af ; .. and free memory indicator ld c,CPMVSN ;Get CP/M version call bdos cp 30h ;Only interested if 2.2 or earlier .. jr nc,vsn3 ; .. so skip if MP/M, CP/M+, TurboDOS pop af ;Recover memory page count ld hl,ccpPages ;Point at CP/M 2.2 CCP size sub (hl) ;See if enough memory without overwriting CCP pop hl ;Recover exit flag pointer jr c,enufMem ;Skip if we will overwrite the CCP ld (hl),1 ;Otherwise set the 'CCP return' exit flag jr enufMem vsn3: pop hl ;CP/M 3 etc - discard values saved on stack pop hl ; (Looks like the foregoing code could be optimised a bit) enufMem: ld a,(lines) ;Set number of lines per screen ld (lps),a ;(Done this way for ZCPR re-entrancy) sub 2 ld (linesLeft),a ld hl,ddma ;Point at command line length prefix ld de,cmdTail ;Point at local copy push de ;Save local copy pointer for a moment ld bc,80h ;Bytes to copy ldi ;Copy length byte deTab: ld a,(hl) ;Fetch byte from command tail cp HT ;Convert TABs to blanks to save dealing jr nz,cmdCopy ;with TABs during command-line parsing ld (hl),' ' cmdCopy: ldi jp pe,deTab pop hl ;Recover local command pointer inc hl ;Point past length byte ld (cmdPtr),hl ;Store pointer (for ZCPR reentrancy) dec hl ;Step back to length byte ld a,(hl) ;Get command length or a jr z,signOn ;Skip if zero length ld e,a ;Point at end of command tail ld d,0 add hl,de ld a,(hl) ;Get last character of command cp 'N' ;Check if it could be a "no page" option jr nz,signOn ;Skip if not dec hl ;Found N but check previous character ld a,(hl) ;(Must be space or tab) cp ' ' ;Space is OK jr nz,signOn ;If not space then cannot be "no page" option xor a ;Clear the "lines per page" counter ld (lps),a ld (hl),a ;Cover the "no page" switch for later parsing ld hl,ddma ;and adjust the counter to new length dec (hl) dec (hl) signOn: ld a,0FFh ;Specifies "get" as opposed to "set" call setUsr ;Get current user number ld (userNo),a ;Save it for later restoration ld c,CURDSK ;Get current disk call bdos inc a ;Convert 0-15 to 1-16 ld (diskId),a ;Save it as default ld a,(useBYE) ;This will be zero if and only if this program or a ; is to run on a non-BYE5 RCPM jr z,setLines ld c,SGUSER ;BYE5 test ld e,241 call bdos sub 77 push af ;Save BYE5 test result ld (byeFlag),a ld a,(userNo) ;Switch back to original user number call setUsr ;(This was wrong in v.12 - thanks Bob Freed) ld hl,heading ;Print heading line call message ld hl,0 ;Clear the file count ld (files),hl xor a ;Clear the "restricted" flag ld (restricted),a ld h,a ;Clear the line limit ld l,a ld (maxLines),hl ld iy,limits ld a,(maxDrv) ;Set the drive/user limits ld (iy+drive),a ;(We do it this way for re-entrancy) ld a,(maxUsr) inc a ld (iy+user),a pop af ;Recover BYE5 test result jr nz,noRestrict ;Skip if BYE5 is not running ld hl,(wheel) ;Test if privileged user ld a,(hl) or a jr nz,noRestrict ;Skip if privileged user ld c,MXDRV ;Get maximum allowed drive ld e,0FFh call bdosy ;I know BYE5 won't touch IY but I'm paranoid ld (iy+drive),a ;Set internal maximum drive number ld c,MXUSR ;Get maximum allowed user area ld e,0FFH call bdosy inc a ld (iy+user),a ;Set internal maximum user setLines: ld hl,(lineLimit) ;Set the line-count limiter ld (maxLines),hl ld a,2Fh ;Any non-zero number ld (restricted),a ;Remember this is a restricted environment noRestrict: ld hl,ddma ;Pointer to beginning of command tail call fnb ;Find non-blank jp z,usage ;============================================================================= ; ; Section 2 - Command-line processing ; ;============================================================================= ; ; Step through the filenames on the command line processing each in turn. ; Ambiguous file names are allowed. At this point cmdPtr points into the ; command buffer at what should be the first character of a file name. cmdLine: call doArg ;Process this command line argument ld hl,(matches) ;Number of files that matched argument ld a,h ;Test for zero or l call z,noMatch ;Say if no files matched ld hl,(cmdPtr) ;Retrieve pointer to it call fb ;Skip to blank call fnb ;Skip to next argument (if any) ld (cmdPtr),hl ;Save argument pointer jr nz,cmdLine ;Loop while more arguments to process ; We get here when all files are processed. Before exiting we check to ; see if at least one file name matched one of the arguments. ld hl,(files) ld a,h or l jp nz,exit ;Exit normally if at least one file seen jp usage ;Exit with instructions if no file seen noMatch: call newLine call hili2 ld hl,noFiles ;Point at message call typeStr ;Display it ld hl,(cmdPtr) ;Point at current argument call showArg ;Display it call normal call newLine ret showArg: ld a,(hl) ;Display argument which matched no file inc hl or a ret z cp ' ' ret z push hl call iType pop hl jr showArg noFiles: db "No file matched ",0 ;----------------------------------------------------------------------------- ; ; Process current command-line argument. It SHOULD be a file name. ; ;----------------------------------------------------------------------------- doArg: ld iy,limits ld ix,du ; Point at drive/user work area xor a ; Set drive/user to ld (ix+drive),a ld (ix+user),a ld (ix+uSpec),a dec a ld (mfFlg1),a ld hl,(cmdPtr) ;Point at filename in command line ld bc,4 ;Colon must be in first 4 characters push hl ld a,':' ;Search for a colon cpir pop hl ;Point back at command line jr nz,duDone ;Skip if there wasn't one ;If we get here then there was a colon in the command tail. We will ;scan that part of the command tail preceeding the colon and attempt to ;extract a drive/user specification. nxtChr: ld a,(hl) ;Pick up a byte from the command tail inc hl cp ':' ;Test for colon terminator jr z,duDone ;Exit if done cp '0' ;Check for a digit jr c,chkDrv cp '9'+1 jr nc,chkDrv call cnvUsr ;Build user number jr nxtChr chkDrv: sub 'A' ;Check for ",0 ;----------------------------------------------------------------------------- ; ; File-level exit routine for typeZ and typeQ. A control-X ; branches to here, as does normal exit. ; ;----------------------------------------------------------------------------- ctrlXit: call closer ;Close file. Ignore any error ret ;Exit to multi-file handler ;----------------------------------------------------------------------------- ; ; printFCB - displays a file name from an FCB ; ;----------------------------------------------------------------------------- printFCB: call hili1 ld ix,du ld a,(ix+drive) ;Get the drive number add a,'@' ;Convert to a letter call uType ;Display it ld a,(ix+user) ;Pick up the user number ld e,'0'-1 tens: inc e ;Calculate the tens digit sub 10 jp p,tens add a,'0'+10 ;Calculate the units digit ld d,a ;Save it while printing the tens digit ld a,e cp '0' ;Is tens digit zero? jr z,units ;If so then don't bother printing it push de call uType ;Display tens digit pop de units: ld a,d ;Recover units digit call uType ;Display units ld a,':' ;Separator call uType ld hl,FCB ld b,8 ;Maximum number of chars to display call printPart ld a,'.' call uType ld hl,FCB+8 ;Now do the same thing for the extension ld b,3 ; call printPart ; ret printPart: inc hl ;Point at file name byte ld a,(hl) ;Pick up a file name byte cp ' ' ;Space marks the end ret z push hl push bc call uType ;Display byte pop bc pop hl djnz printPart ret ;----------------------------------------------------------------------------- ; ; Check file name extension pointed to by HL against exclusion ; list. Set carry flag if file extension is in the list. ; ;----------------------------------------------------------------------------- exclude: ld de,exList ;Point to exclusion list excl1: ld a,(de) ;Check for end of table or a ret z ;Exit with carry flag OFF if end of table push hl ;Save name extension pointer ld b,3 ;Number of characters to check excl2: ld a,(de) ;Get byte from table cp '?' ;Match anything? jr z,ambig ld c,(hl) ;Get byte from file name extension res 7,c ;Clear attribute bit cp c ;Check file name extension character jr nz,nextMem ;Skip to next table entry if different ambig: inc de ;Step the pointers inc hl djnz excl2 ; If we get here then the file name extension matches a table entry. ; We clean up the stack and exit with the carry flag set. pop hl ;Recover extension pointer ld de,badExtn ;Point at slot in message ld bc,3 ;Number of bytes to copy ldir ;Move offending extension into message scf ;Exit with carry flag set ret ; Step to next table member and restore name extension pointer nextMem: inc de ;Step to next table entry djnz nextMem pop hl ;Recover name pointer jr excl1 ;Loop back for next match noType: ld hl,untypeable inform: push hl call hili2 pop hl call typeStr call normal call newLine scf ret untypeable: defb " --- Can't type ." badExtn: defs 3 defb " files",0 empty: ld hl,nullFile jr inform nullFile: defb " --- Empty file",0 ;----------------------------------------------------------------------------- ; ; Open for reading the file addressed by the contents of the default ; FCB at 5Ch. ; ;----------------------------------------------------------------------------- openIt: ld hl,256 ;Set input pointer past end of buffer ld (bufAd),hl ; to force read on first access ld de,fcb ;Open the file addressed by FCB ld c,OPEN call bdos or a ;Clear carry flag (which gets set if in .LBR) inc a ;Test for error ret nz ;No error - initialise for reading call hili2 ld hl,badOpen ;Report the error call print scf ret ;------------------------------------------------------------------------------ ; ; Fetch a byte from the file pointed at by the default FCB at 5Ch. ; ; Returns with carry flag set if at end of file. ; ;------------------------------------------------------------------------------ getByt: ;Synonym for readIt required for linking readIt: ld hl,(bufAd) ld a,h ;Time to read? or a jr z,noRd ;No ld de,fcb ld c,READ ;Read another sector of file call bdos or a ;Check return code jr nz,finish ld hl,ddma noRd: ld a,(hl) ;Get a character inc hl ld (bufAd),hl ;Update buffer address or a ;Clear the carry flag ret ;Read some more characters finish: push af ;Save return code call closer ;Close the file pop af ;Recover return code cp 1 ;Normal end of file? jr z,finish1 ;Yes ld hl,readErr call message xor a inc a scf ;Signal EOF ret finish1: xor a scf ret closer: ld de,fcb ;Close the file ld c,CLOSE call BDOS scf ;Signal EOF ret badOpen: defb CR,LF,"<>",CR,LF,'$' readErr: defb CR,LF,"<>",CR,LF,'$' ;============================================================================= ; ; Section 4 - Character output routines ; ;============================================================================= ;----------------------------------------------------------------------------- ; ; Outputs the character in the A register to the console after ; checking that the stuff we are printing is "nice" text. ; ;----------------------------------------------------------------------------- out: and 7Fh ;Clear any high bits cp CPMEOF ;Check for textfile EOF scf ;Set carry flag in case it is EOF jp z,fileEnd ;Exit if EOF cp FF ;Translate formfeed to cr/lf jp z,newLine ld e,a ;Store character for output ; Determine whether or not we are printing rubbish. Quite arbitrarily ; I use an algorithm which says that a file is unprintable if any three ; of the last eight characters are non-graphic. ld hl,ngFlags ;Point at non-graphic flags cp CR ;Carriage return OK jr z,ngTest cp LF jr z,ngTest cp HT jr z,ngTest cp BEL jr z,ngTest cp BS jr z,ngTest cp 20h ;Check for graphic jr c,ngTest ;Non-graphic if < space cp DEL ;Non-graphic if DEL ccf ;C flag reset if graphic ngTest: ld a,(hl) ;Get the non-graphic flags rla ;Load in the new non-graphic flag ld (hl),a ;Store it for next time or a ;Clear the carry flag jr z,allOK ;Skip the bit-counting if all zero ld b,8 ;Load rotation counter ld c,0 ;Clear bit counter bits: rra ;Shift out a bit jr nc,unset ;Skip if it was a graphic character inc c ;Count the non-graphics unset: djnz bits ;Loop until all counted ld a,2 ;Allow two bad characters cp c ;If 3 or more then jp c,quit ; stop this farce allOK: ld a,e ;Recover output character ; call type ;Output character from A register ; ret ;----------------------------------------------------------------------------- ; ; Outputs character in A register to console after filtering out ; potentially damaging control characters. ; ; If paging is not disabled then also counts lines and when page ; limit is reached displays [more] prompt and waits for a keypress. ; ; Also checks for ^C abort, ^X to skip this file, ^S pause. ; ;----------------------------------------------------------------------------- type: push af ;Save output character for line count call filter ;Suppress unfriendly characters call nc,putc ;Display character if not dangerous pop af ;Recover output character cp LF ;Only interested in these jr nz,ckAbort ;For others, go check keyboard ld hl,(lineCount) ;Check line limit ld a,h ;Test for initial (or current) value of zero or l ; (i.e. no limit) jr z,paging ;Skip if no limit dec hl ;Count down the lines ld (lineCount),hl ld a,h ;Test for zero now or l ; (i.e. limit reached) jr nz,paging ;Skip if limit not yet reached ld hl,download ;Tell user to download the file call message ;Recursive call on "type" routine! jr fileEnd paging: ld a,(lps) ;Get lines per screen or a ;Test if paging jr z,ckAbort ;If not then go check keyboard ld hl,linesLeft ;Point at lines remaining on screen dec (hl) ;Count down jr nz,ckAbort ;Exit if room left ld a,(lps) ;Get lines per screen dec a ;Deduct two for continuity dec a ld (hl),a ;Restore full screen count ld hl,more ;Point at end-of-screen prompt call uTypeStr ;Display without interrupt call getch ;Fetch character without echo call resume ;Check for ^C, ^X abort push af ;Save result of test ld hl,rubMore ;Clear the prompt from the screen call uTypeStr pop af ;Recover result of ^C ^X test jr c,fileEnd ;Exit ret more: db ' [More]',CR,0 rubMore: db ' ',CR,0 ;----------------------------------------------------------------------------- ; ; Get keyboard input and execute appropriate action... ; ; ^S pauses listing ; ^X skips the rest of this file ; ^C aborts altogether ; ; Any other character is ignored except will resume listing ; if currently paused. ; ;----------------------------------------------------------------------------- ckAbort: call kbhit ;Any key pressed? ret z ;Exit if not cp DC3 ;^S (XOFF)? jr nz,thaw call getch ;Wait for something thaw: call resume jr c,fileEnd ret resume: cp ETX ;^C? jp z,exit ;Terminate cp CAN ;^X? scf ;Clear Carry flag without touching ccf ;the Zero flag ret nz ;Carry flag off if not ^X scf ;Carry flag on if ^X ret fileEnd: ;Restore the stack to whatever it was before we called ;the output routine and exit back to the multi-file loop. ld sp,(myStk) ret download: db 'Enough! - you are better off downloading the file',0 ;----------------------------------------------------------------------------- ; ; Output filter - prevents unwanted control characters from ; being sent to the screen. Exits with carry flag set if ; character is NOT to be printed. ; ;----------------------------------------------------------------------------- filter: cp DEL ;DEL not to be printed scf ret z cp 20h ;Anything else from ' ' upwards is OK ret nc cp HT ;HT is OK and will be expanded ret z cp CR ;CR is OK ret z cp LF ;LF is OK ret z scf ;Anything else is not to be printed ret ;----------------------------------------------------------------------------- ; ; Turn up a new line on the screen. ; ;----------------------------------------------------------------------------- newLine: ld a,CR call type ld a,LF call type ret ;----------------------------------------------------------------------------- ; ; Report unprintable characters and exit this file ; ;----------------------------------------------------------------------------- quit: ld hl,junk call message jp fileEnd junk: defb 'Seems to be a lot of rubbish', 0 ;-------------------------------------------------------------------------- ; ; Standard character output routine ; ;-------------------------------------------------------------------------- putc: ld hl,col ;Point at column counter cp HT ;TAB? jr z,expand ; - convert to multiple spaces cp CR ;Carriage return? jr z,col0 ; - reset column counter cp ' ' ;Non-spacing character? jr c,uType ; - print but don't increment column counter inc (hl) ;Increment column counter jr uType ;Output character col0: push hl call uType ;Output the CR pop hl xor a ;Get a zero ld (hl),a ;Clear column count ret expand: ld a,(hl) ;Get column count and 7 ;Calculate number of spaces needed neg ; to put cursor at next multiple add a,8 ; of 8 columns ld b,a ;Space counter to B for loop expTab: ld a,' ' ;Get a space for output push bc ;Save loop counter inc (hl) ;Update column push hl ;Save pointer call uType ;Output the space pop hl ;Recover column pointer pop bc ;Recover loop counter djnz expTab ;Continue until at required column ret ;-------------------------------------------------------------------------- ; ; Uninterruptable character output routines ; ;-------------------------------------------------------------------------- uType: ld e,a ld c,CONIO call BDOS ret uTypeStr: ld a,(hl) inc hl or a ret z push hl call uType pop hl jr uTypeStr ;-------------------------------------------------------------------------- ; ; Interruptible string output routine (sensitive to ^S, ^C) ; ;-------------------------------------------------------------------------- typeStr: ld a,(hl) inc hl or a ret z push hl call iType pop hl jr typeStr iType: call uType call kbhit ;Any key pressed? ret z ;Continue if not cp DC3 ;^S (XOFF)? call z,getch ;Wait for something cp ETX ;^C? ret nz ;Continue if not jp z,exit ;Terminate ;-------------------------------------------------------------------------- ; ; getch - Fetch a character from the keyboard without echo ; ;-------------------------------------------------------------------------- getch: call kbhit ;Test if key pressed jr z,getch ;Loop until one is ret ;Exit with character in A kbhit: ld a,0FFh call uType or a ;Set Z flag if nothing typed ret ;-------------------------------------------------------------------------- ; ; Video highlighting routines ; ; Safe to use in an RCPM environment because video codes won't ; be sent out over the data communications link. ; ;-------------------------------------------------------------------------- hili1: ld hl,hiVid1 jr video hili2: ld hl,hiVid2 jr video normal: ld hl,normVid video: ld a,(hl) ;Check if video attributes enabled or a ret z ;Exit if not ld b,a ;Count of bytes to output ld c,CONIO ;Preload console I/O function ld a,(byeFlag) ;Is BYE running? or a jr nz,vidOut ;Skip if it isn't running ld c,LOCO ;Local console output BDOS function vidOut: inc hl ;Point to character ld e,(hl) ;Fetch it for output push bc ;Save BDOS function and character counter push hl ;Save character pointer call bdos ;Output character to local console pop hl ;Recover character pointer pop bc ;Recover BDOS function & character counter djnz vidOut ;Loop until all sent ret ;-------------------------------------------------------------------------- needZ80: db "This program requires a Z80 processor$" tooSmall: db "Not enough memory to run this program$" heading: db "TYPEQZ " db '0'+version db '.' db '0'+revision db " ^S=pause, ^C=abort, ^X=next file",0 howTo: ; 1111111111222222222233333333334444444444555555555566666 ; 1234567890123456789012345678901234567890123456789012345678901234 db "Command format is: TYPE afn [afn ... ] [N]",cr,lf db "where 'afn' is a (possibly ambiguous) file name which can be",cr,lf db "prefixed by a drive and/or user specification, e.g:",cr,lf db cr,lf db " 13B:*.A?M B13:*.A?M 13:*.A?M B:*.A?M",cr,lf db cr,lf db "Multiple afn's can be requested. For example,",cr,lf db cr,lf db " C2>TYPE 0A:ONLINE B4:-*.* B5:-*.* *.A?M 0:*.C?",cr,lf db cr,lf db "would list 'ONLINE' from A0:, all files starting with '-' from",cr,lf db "B4: and B5:, all plain, crunched and squeezed .ASM files from",cr,lf db "C2: and all plain, crunched and squeezed .C files from C0:.",cr,lf db cr,lf db "Typeout normally pauses at each screenful unless the very last",cr,lf db "thing on the command line is 'N' (no paging).",0 du: defs 3 drive equ 0 user equ 1 uSpec equ 2 col: defs 1 $memry: defs 2 tExtn: defs 3 defb 0 ;----------------------------------------------------------------------------- ; ; Uninitialised data items ; ;----------------------------------------------------------------------------- restricted: defs 1 ;Set if BYE5 and not WHEEL limits: defs 2 ;Maximum DU: ngFlags: defs 1 ;Tally of non-graphic characters files: ds 2 ;Number of files processed/seen matches: ds 2 ;Number of files matching current argument lps: ds 1 ;Lines per screen (0 if not paging) linesLeft: defs 1 ;Number of lines remaining on the screen maxLines: ds 2 ;Maximum number of lines per file to type lineCount: defs 2 ;Line counter userNo: ds 1 ;User number at invocation diskId: ds 1 ;Current disk at invocation bufAd: ds 2 ;Buffer pointer cmdPtr: defs 2 ;Pointer into command tail cmdTail: defs 80h ;Copy of command tail mfCur: ds 12 ;Used by MFNAME routine mfReq: ds 12 ; ditto mfFlg1: ds 1 ; ditto byeFlag: ds 1 ;Zero(!) if BYE5 is running ccpRet: ds 1 ;Flag to say if OK to exit with a RET to CCP myStk: ds 2 ;Holds stack pointer for ^X abort ccpStk: ds 2 ;Stack pointer on entry to program ds 64 ;Adequate stack space for our own use locStk: ;----------------------------------------------------------------------------- end start .list