;--------------------------------------------------------------------- ; SPQ.ASM program to list spool queue entries ; For CP/M+ Print Spooler Version 1.3 (development version) ;--------------------------------------------------------------------- ; qlist equ 44 ; RSX function code to return spool queue address ; extrn conchr ; Print char A at console extrn cnchrs ; Print char C at console B times extrn cncrlf ; Print at console extrn cstrng ; Print '$' terminated string at console extrn cmphd ; Compare HL & DE extrn pnamef ; Print filename with fcb [DE] extrn pdecml ; Print decimal value of HL extrn inkey ; Get key or 0 if none pressed (BDOS#6) extrn clview ; Clear viewport extrn home ; Home cursor ; ;--------------------------------------------------------------------- ; jp gospq ; db 'SPQ v1.31 ' db '(c) 9th May, 1989 by Andy Metcalfe ' ; gospq: ld sp,stack ld c,getver call bdos ; Version check cp 31h ld de,noplus jp c,error ; No go if earlier than v3.1 ; ld a,(cpmfcb+1) ; First byte of command line tail ld (spcont),a ; If this byte is 'C', will loop until ; Spool finished or user quits ; sqloop: ld a,qlist ld (rsxpb),a call gorsx ; HL=queue list data address or 00ffh ld de,00ffh call cmphd ; No answer? jp z,qnowt ; Don't proceed if queue empty ; ld a,(hl) or a jp z,qnowt ; Qnow=0, so queue empty ; push af ld a,(qold) ; Qnow from last time round ld b,a pop af cp b ; Has qnow changed? ld (qold),a ; Save qnow for next time call nz,pqueue ; Yes: print queue contents ; ld a,(spcont) cp 'C' ; Check whether user wants continuous display jp nz,spquit ; No - drop out call inkey or a ; Keypress? jp z,sqloop ; Loop until keypress entered or spool completed spquit: ld c,wboot jp bdos ; Warm boot ; ;--------------------------------------------------------------------- ; Jump here if queue empty ; qnowt: call clview call home ; Clear viewport & home cursor ld de,qempty jp error ; Print message & reboot ; ;--------------------------------------------------------------------- ; Routine to print spool queue contents ; Enter with HL=queue address, as returned by RSX, and A=qnow. ; pqueue: ld (qnow),a ; Store qnow push af inc hl ld a,(hl) ld (qnext),a ; Pointer to next free element inc hl ld a,(hl) ld (qmax),a ; Max no of queue entries inc hl ; HL addresses first queue entry ; call clview ; Clear viewport call home ; Home cursor ld de,header call cstrng ; Print title line ld c,'-' ld b,72 call cnchrs ; Print ruler line call cncrlf ; pop af ; A=qnow as index ld c,a ; C=queue index no ld b,1 ; B=counter ld a,(qmax) ld e,a ; E=max queue entries or default no free ld (qstart),hl ; Save address of queue start ; ploop: push de ; Save "free entries" down counter ld hl,(qstart) ; HL=address of start of queue ex de,hl ; To DE ld a,c ; A=queue index no dec a ; No of 16 byte entries to add to start address call mlt16 ; HL=offset add hl,de ex de,hl ; DE addresses current queue entry ld hl,12 add hl,de ; HL=address of index no in queue entry ld a,(hl) ld (qindex),a ; Saved inc a ; Index no=0ffh? jp z,noprt ; Yes - skip print ; push bc ; Save counters (B=position, C=index no) push hl ; Save address of index no push bc ld c,' ' ld b,3 call cnchrs ; Print 3 leading spaces before queue position pop bc ld l,b ; Queue position counter ld h,0 call pdecml ; Print decimal value ld a,tab call conchr call conchr ; Print two tabs ex de,hl ld a,0ffh ; Tells pnamef to print user no as well call pnamef ; Print user no, drive & filename ld a,tab call conchr ; Another tab ld a,' ' call conchr call conchr ld a,(qindex) ld l,a ld h,0 call pdecml ; Print index no ld a,tab call conchr ; This is getting repetitive...yet another tab... pop hl ; Address of index no inc hl ; HL addresses size entry call psizef ; Print size in kbytes pop bc ; ld a,b ; A=position in queue (not index no) dec a ; A=Is this file the first? jp nz,not1 ; No: skip next bit ; ld a,tab call conchr ld de,prtmes call cstrng ; Display "*** Printing ***" message ; not1: call cncrlf ; New line inc b ; Increment no of entries noprt: inc c ; Increment queue index no ld a,(qmax) cp c ; Does this make qnow>qmax? jp nc,wrapit ; No: skip ld c,1 ; Yes: start again at qnow=1 wrapit: pop de ; E="free entries" down counter dec e ; Subtract one for last entry ld a,(qnext) cp c ; Has qnow reached qnext, ie at end of queue jp nz,ploop ; No: loop back for next file ; push de ; Save free entries counter call cncrlf call cncrlf dec b ; B=no of queued entries ld de,qnomes call cstrng ld l,b ld h,0 call pdecml ; Display "No of queued entries = m" call cncrlf ld de,fremes call cstrng pop de ; E=no of free queue entries ld d,0 ex de,hl call pdecml ; Display "Number of free queue entries = n" call cncrlf jp cncrlf ; Down a line & ret ; ;--------------------------------------------------------------------- ; Error handler ; error: call cstrng ld c,wboot jp bdos ; ;--------------------------------------------------------------------- ; Call RSX using parameter block [rsxpb] ; gorsx: ld de,rsxpb ld c,calrsx jp bdos ; ;--------------------------------------------------------------------- ; Print file size [HL] (number of 128 byte records) in kbytes. ; Can cope with file sizes up to 32767kbytes (32Mbytes). ; psizef: push hl push de push bc ld e,(hl) inc hl ld d,(hl) inc hl ld c,(hl) ex de,hl ld a,l and 07h ; Mask out top five bits push af ; Flag byte: if A>0 add one to size in kbytes ld b,3 ; Need to shift bytes 3 bits to right ; psize2: and a ; CY=0 ld a,c rra ; Rotate C right: lsb in CY ld c,a ld a,h rra ; Rotate H right: msb from CY, lsb to CY ld h,a ld a,l rra ; Rotate L right: msb from CY, lsb to CY ld l,a dec b ; Counter jp nz,psize2 ; pop af jp z,psize3 ; Nothing to add inc hl ; Add one to bottom 2 bytes psize3: call pdecml ; Print size in kbytes ld a,'k' call conchr ; Print suffix pop bc pop de pop hl ret ; ;--------------------------------------------------------------------- ; Routine to multiply A by 16, returning result in HL. ; All registers preserved. ; NOTE: Alternative method would be to copy A to HL, then shift ; left 4 times. ; mlt16: push de push af ld hl,0 ld de,16 mlt16a: or a jp z,mlt16b add hl,de dec a jp mlt16a ; mlt16b: pop af pop de ret ; ;--------------------------------------------------------------------- ; Program messages ; dseg ; noplus: db 'Sorry, this program requires CP/M+',cr,lf,'$' ; qempty: db cr,lf,'*** The Spool Queue Is Empty ***',cr,lf,'$' ; header: db cr,lf,'Position',tab,' Filename',tab,tab,'Index',tab,'Size' db cr,lf,'$' ; prtmes: db '*** Printing ***$' ; qnomes: db 'Number of queued files = $' ; fremes: db 'Number of free queue entries = $' ; ;--------------------------------------------------------------------- ; Scratch Pad Area ; qnow: ds 1 qold: db 0ffh ; 0ffh forces first print loop qnext: ds 1 qmax: ds 1 qindex: ds 1 rsxpb: ds 2 qstart: ds 2 spcont: ds 1 ds 50 stack equ $ ; end