; WHATSN05 - Displays XMODEM.LOG (or LOG.SYS) in reverse order - 03/01/86 ; ; WHATSNEW.ASM ; by ; Irvin M. Hoff ; (01 March 1986) ; ASEG ; For M80 and RMAC, ignore if using MAC ; ; ; This program is really two-in-one. It is for use with RCPM systems ; having a XMODEM.LOG (or LOG.SYS) of all file transfers created by the ; XMODEM file transfer program. (If using MBYE, substitute the term ; LOG.SYS wherever appears and set the MBYE equate to YES.) ; ; Program 1 = shows the XMODEM.LOG in reverse order, newest first ; Program 2 = shows only uploads in reverse, ignoring downloads ; ; WARNING: Versions of XMODEM prior to 101 did not ; mark uploads to private areas differently ; from normal uploads. ; ;======================================================================= ; ; 03/01/86 - Added pagination, also allowed WHEEL users to specify ; v05 WHATSNEW A to see uploads and downloads without maintaining ; a second copy of program online. - Michael Conley ; ;======================================================================= ; ; SHOWAL set to 0 - gives Program 1 ; --------------------------------- ; Before configuring this, note that WHEEL users may show all files by ; typing "WHATSNEW A" on the command line, regardless of SHOWAL equate. ; ; When the SHOWAL option is set to "0", all files in the XMODEM.LOG are ; shown in reverse order. This is particularly useful to SYSOPs to see ; who has most recently uploaded/downloaded any files and what they are. ; It can be placed in A15: with other private .COM files or A0: for all ; to use, if desired. Call this program ALL.COM for easy reference. ; ; SHOWAL set to 1, gives Program 2 ; -------------------------------- ; This program displays the "R" (new files) entries entered by XMODEM ; into the XMODEM.LOG file, in inverse order. It replaces the WHATSNEW ; files used in the past for RCPM systems. (If the wheel byte is set ; for the SYSOP's use, it includes any "P" private uploads. These are ; shown with an "*" after the drive/user number.) This program is de- ; signed to work with XMDM101 or later. It may need to be customized ; slightly, depending on how your LASTCALR file is arranged. It goes in ; the A0: area and can be called from any drive/user area. It is essen- ; tially self-maintaining, which makes it quite different from WHATSNEW ; programs previously used, made via D-29, etc. It is 1k long and fully ; secure. (Change equates below if your XMODEM.LOG isn't in A14: area.) ; ; NOTE: You can use DDT to set the following byte: ; ; 0103H 00 program 1, shows all file transfers ; 01 program 2, uploads only, for WHATSNEW. ; ; Then A>SAVE 5 NEW.COM ; ; Suggestion: Make one of each, call one ALL.COM and put on ; A15: for easy use by the SYSOP and the other ; WHATSNEW.COM and put on A0: for all to use. ; ;----------------------------------------------------------------------- ; ; INFO: ; ---- ; A companion program currently called XMDEL automatically ; deletes all downloaded files from XMODEM.LOG, keeping ; the uploads for WHATSNEW. This minimimizes the length ; of the XMODEM.LOG file, since "most" of the lines are ; for downloads. The combination of WHATSNEW and XMDEL make ; the entire new file display almost fully self-maintaining. ; ;----------------------------------------------------------------------- ; ; OPTIONS: ; ------- ; SHOWAL 0 = Shows all files in the XMODEM.LOG in reverse manner ; Makes this into a second program, see below ; 1 = Allows options above to work normally ; ; OPTION 0 = No header, shows "R" lines of XMODEM.LOG "as is". ; 1 = Header, uses example 1 below (OxGate 001 system) ; 2 = Header, uses example 2 below (Potpourri system) ; ; HEADER 0 = No header, regardless of option below ; 1 = use header selected by option below ; ;--------------- ; ; Example 0: (no header, no changes, before and after the same. Picks ; out the "R" lines from the XMODEM.LOG and displays in re- ; verse order (newest uploads, first). ; ;--------------- ; ; Example 1: OxGate 001 (before) ; ; R6 02:22 B00>WHATSNEWLBR 26k Irv Hoff 1/22/85 ; ; (after) ; ; D/U Filename Size Speed Uploaded by ; ; B00: WHATSNEW.LBR 26k 1200 bps Irv Hoff 1/22/85 ; ;--------------- ; ; Example 2: Potpourri (before) ; ; R6 02:22 B00>WHATSN01LBR 26k 01/22/85 16:44 Irv Hoff ; ; (after) ; D/U Filename Size Speed Date Time Uploaded by ; ; B00: WHATSN01.LBR 26k 1200 bps 01/22/85 16:44 Irv Hoff ; ;----------------------------------------------------------------------- ; ; Features: ; --------- ; 1) Should be placed in A0: so any user can call the program ; 2) Should be renamed to WHATSNEW.COM at that time ; 3) Automatically remembers current drive/user area ; 4) Jumps to A14: to read the XMODEM.LOG file, with full security ; 5) Opens the XMODEM.LOG file, if empty says "NO NEW FILES" ; 6) Copies each line starting with "R" into a one-line buffer ; 7) Customizes that line, if OPTION 1 or 2 is selected ; 8) Stores the line in a memory buffer ; 9) When all lines are read, displays them in inverse order, ; thus showing most recent files first. ; 10) CTL-C, CTL-K, CTL-X, C, K, X, c, k, x all will abort after ; finishing the current line. ; 11) Can be called from any drive/user area ; 12) Returns to original drive/user area from which it was called ; 13) WHEEL users may specify "WHATSNEW A" to see uploads and ; downloads regardless of SHOWAL equate setting. ; 14) Pagination added -- equate sets page length or 0 to override ; pagination feature. ; ; The SYSOP can readily customize this program to suit his preferences. ; The area around W7: and TDONE1: would be the sections to customize if ; selection 1 or 2 is not sufficient. ; - Notes by Irv Hoff W6FFC ; ;----------------------------------------------------------------------- ; ; 05/05/85 Added option to select MBYE's LOG.SYS instead of XMODEM.LOG. ; v04 - Irv Hoff ; ; 02/22/85 Modest change to ABORT: area for CTL-S to work with TURBODOS ; v03 systems. - Irv Hoff ; ; 02/07/85 If a file was 100k or more, was not showing the first digit ; v02 on some systems. - Irv Hoff ; ; 02/02/85 Initial version - thanks to Wayne Masters for suggestions. ; v01 - Irv Hoff ; ;----------------------------------------------------------------------- ; ; User choices ; ; NO EQU 0 YES EQU NOT NO ; MBYE EQU NO ; Yes for LOG.SYS, No for XMODEM.LOG ; SHOWAL EQU 1 ; 0=all file transfers, 1=uploads only OPTION EQU 1 ; Must be 0, 1 or 2 (see above) HEADER EQU 1 ; 0=no header, regardless of option ; DRIVE EQU 'A' ; XMODEM.LOG stored here in your system USER EQU 14 ; XMODEM.LOG stored here in your system PGLEN EQU 22 ; paging length / set to 0 for no paging ; WHEEL EQU 03EH ; Location of wheel byte for RCPM use ;----------------------------------------------------------------------- ; ; Equates ; CR EQU 0DH ; Carriage return EOF EQU 1AH ; End of file - ^Z LF EQU 0AH ; Line feed TBUF EQU 0080H ; Default buffer address TCHR EQU TBUF + 2 ; Address of first command line option char. ; ; ;----------------------------------------------------------------------- ; ; BDOS equates ; BDOS EQU 0005H ; CP/M BDOS entry address RDCON EQU 1 ; Get character from console WRCON EQU 2 ; Write character to console DIRCON EQU 6 ; Direct console I/O PRINT EQU 9 ; Print string (DE) until '$' CONST EQU 11 ; Get console status function SELDSK EQU 14 ; Select requested disk drive OPEN EQU 15 ; Open disk file CLOSE EQU 16 ; Close disk file READ EQU 20 ; Read sequential file STDMA EQU 26 ; Set DMA address SETUSR EQU 32 ; Set user area on disk ; ;----------------------------------------------------------------------- ; ; Program starts here ; ; ORG 100H ; JMP START ; ; SHOL: DB SHOWAL ; Shows complete LOG file in reverse OPTN: DB OPTION ; Simple selection without assembling HDR: DB HEADER ; Selects header option ; ; START: LXI H,0 DAD SP ; Get 'CCP' stack SHLD STACK ; Save it for exit LXI SP,STACK ; Set stack pointer ; AOPT: LDA WHEEL ; See if wheel user CPI 0 JZ NOPT ; NO? don't look for options AOPT1: LDA TBUF ; See if option present CPI 0 JZ NOPT LDA TCHR CPI 'A' ; If it's an A, show uploads & downloads JNZ NOPT MVI A,0 STA SHOL NOPT: LDA 0004H ; Get current drive/user STA DRUSER ; Store ; ; ; Set drive/user to the XMODEM.LOG area listed above ; ; Set drive/user to the XMODEM.LOG or LOG.SYS area listed above ; MVI E,USER ; Set user to XMODEM.LOG area MVI C,SETUSR CALL BDOS ; MVI A,DRIVE ; Set drive to XMODEM.LOG area SUI 41H MOV E,A MVI C,SELDSK CALL BDOS ; ; ; Open source file ; CALL ILPRT DB CR,LF,0 LXI D,FILE MVI C,OPEN CALL BDOS INR A ; Check for no open JZ NONE ; No file, exit ; CALL ILPRT DB 'WHATSNEW Type ^S to pause, ^C, ^X or ^K to abort' DB CR,LF,CR,LF,'wait a moment...',0 ; LDA 0007H ; Find end of TPA DCR A ; Do not allow to get too close DCR A STA LENGTH ; store new value for buffer area LXI H,0 ; Reset output pointers SHLD PTR MVI B,EOF ; EOF to terminate reverse reading later CALL SEND1 ; Put in memory MVI B,LF ; Allows a single line to be shown CALL SEND1 ; Put in memory ; ; ; Read sector from source file ; READLP: LXI D,TBUF MVI C,STDMA CALL BDOS ; LXI D,FILE MVI C,READ CALL BDOS ; ORA A ; Read ok? JZ WRDISK ; Yes, send it to output CPI 1 ; End-of-file? JZ TDONE ; Transfer done, close, exit CALL EXIT DB '++ SOURCE FILE READ ERROR ++','$' ; ; ; Write sector to output file (with buffering) ; WRDISK: LXI H,80H ; Read buffer address ; WRDLOP: MOV A,M ; Get byte from read buffer ANI 7FH ; Strip parity bit CPI 7FH ; Del (rubout)? JZ NEXT ; Yes, ignore it CPI EOF ; End of file marker? JZ TDONE ; Transfer done, close, exit MOV B,A ; Save the character for now CPI LF ; New line? JZ SENDLF ; If yes, exit ; ; ; Will show entire XMODEM.LOG in reverse if requested ; LDA SHOL ORA A JZ SEND LDA COLUMN ; See if in first column ORA A JNZ WRDL3 ; If not, exit INR A STA COLUMN ; Won't be in first column any longer ; ; ; Shows "P" entries only if wheel byte is set for SYSOP's use ; MOV A,B ; Get the character back CPI 'P' ; This line a private upload? JNZ WRDL1 ; If not, exit LDA WHEEL ORA A JZ WRD2 ; "P" lines not shown without wheel byte STA PRIVT ; To distinguish "P" lines when shown STA STORE ; Just in case it is JMP WRDL4 ; WRDL1: CPI 'R' ; This a "received file"? STA STORE ; Set the flag just in case JZ WRDL4 ; If 'R', keep the flag set ; WRD2: XRA A STA STORE ; Otherwise reset flag to zero ; WRDL3: LDA STORE ; Storing into memory? ORA A JZ NEXT ; If not, exit ; WRDL4: LDA COLUMN ; Increment the column counter INR A STA COLUMN ; ; ; The following retains original format of XMODEM "R" lines ; LDA OPTN ; Get option ORA A JZ SEND ; If not customizing, exit LDA COLUMN ; Get the column count back CPI 3 ; User's modem speed is in column 2 JNZ WR1 ; If not column 2, continue MOV A,B ; Otherwise get the character STA STORE ; Store it for conversion to baud rate JMP NEXT ; Do not print the "MSPEED" number ; WR1: CPI 11 JC NEXT ; Skip everything through column 9 CPI 14 JC SEND ; Print everything through column 12 JNZ WR4 LDA PRIVT ; Going to distinguish a "P" line? ORA A JZ WR2 XRA A STA PRIVT MVI B,'*' CALL SEND1 JMP WR3 ; WR2: MVI B,':' ; Stick in a colon after column 12 CALL SEND1 ; WR3: MVI B,' ' ; Send a space JMP SEND ; WR4: CPI 22 ; Print through column 20 JC SEND JNZ WR5 CALL SEND1 ; Send character in colum 21 MVI B,'.' ; Add a period after the file name JMP SEND ; WR5: CPI 27 JC SEND ; Print file type and some spaces CPI 39 JC NEXT ; Ignore the "big gap" CPI 43 JC SEND ; Print the file size JZ WR6 ; ; ; Customizes area after the file size ; LDA OPTN CPI 1 JZ SEND ; If option 2, exit LDA COLUMN ; Get the column count back again JMP WR7 ; If not column 42, continue ; WR6: CALL SEND1 ; Print first space CALL SEND1 ; Add two extras CALL BAUD ; Print the baud rate and two spaces JMP NEXT ; WR7: CPI 52 JC SEND ; Print the date JNZ WR8 CALL SEND1 ; Print first space after date JMP SEND ; Add a space ; WR8: CPI 58 JC SEND ; Print the time program was sent JNZ SEND ; If not column 57, continue CALL SEND1 ; Print the first space CALL SEND1 ; Add two spaces JMP NEXT ; Continue with rest of line (name) ; SEND: PUSH H ; Keep buffer address MOV A,B ; Get the character back CALL OUTCHR POP H ; Get input buffer address back ; NEXT: INR L ; Done with sector? JZ READLP ; If yes get another sector JMP WRDLOP ; No, get another byte ;... ; ; SEND1: PUSH H ; Keep buffer address MOV A,B ; Get the character back CALL OUTCHR POP H ; Get input buffer address back RET ;..... ; ; SENDLF: XRA A STA COLUMN ; Othewise in column 0 now CALL ABORT ; Want to quit already? LDA SHOL ; Showing entire XMODEM.LOG? ORA A JZ SENDL1 LDA STORE ; End of a "R" line? ORA A JZ NEXT ; If not, ignore this "LF" ; SENDL1: INR A ; Just to get a positive value STA COUNT ; Have at least one line to show LDA LAST+1 ; Get "H" value of current memory MOV C,A ; Store temporarily LDA LENGTH SUB C JNC SEND CALL SEND1 ; Put the LF into memory JMP TOLONG ; If same or more, memory full ;..... ; ; ;----------------------------------------------------------------------- ; ; SUBROUTINES ; ;----------------------------------------------------------------------- ; ; Aborts the display when requested, but only at end of line ; ABORT: PUSH H PUSH D PUSH B MVI C,DIRCON ; See if anything from console MVI E,0FFH ; CALL BDOS ; CPI 0 ; NO KEY? JZ CKPAG ABORT0: ANI 5FH ; Convert to upper case ORI 40H CPI 'C' JZ ABORT1 CPI 'K' JZ ABORT1 CPI 'S' ; How about S? JZ FINGER ; If so, pause till next key CPI 'X' JZ ABORT1 CKPAG: MVI A,PGLEN ; Are we paging? CPI 0 JZ NOABT ; no, return LDA PGCNT ; pickup current count MOV B,A ; save in b MVI A,PGLEN ; get total length SUB B ; minus current count CPI 0 JZ FINGER ; equal? then pause NOABT: POP B POP D POP H RET ; ABORT1: POP B ; Restore the registers POP D POP H POP H ; Clear "CALL ABORT" from stack CALL EXIT ; If yes, then print abort message DB CR,LF,'++ ABORTED ++','$' ; ; FINGER: CALL ILPRT DB '[more]',CR,0 FING1: MVI C,DIRCON ; Check to see if key pressed MVI E,0FFH CALL BDOS CPI 0 JZ FING1 ; If no key pressed, then wait more PUSH PSW ; save the char XRA A STA PGCNT POP PSW JMP ABORT0 ; otherwise go back and check char ;..... ; Backs up to the start of the previous line ; BACKUP: DCX H MOV A,M CPI EOF JZ BACK1 CPI LF ; End of line character? JNZ BACKUP ; IF NOT, KEEP REVERSING RET ; BACK1: POP H ; Restore stack JMP TDONE4 ; All finished this file ;..... ; ; ; Shows the received baud rate ; BAUD: LDA STORE CPI '0' JZ B110 CPI '1' JZ B300 CPI '5' JZ B1200 CPI '6' JZ B2400 MVI B,' ' CALL SEND1 CALL SEND1 CALL SEND1 CALL SEND1 JMP BFIN2 ;... ; ; B110: MVI B,' ' CALL SEND1 MVI B,'1' CALL SEND1 MVI B,'1' CALL SEND1 JMP BFIN1 ; B300: MVI B,' ' CALL SEND1 MVI B,'3' JMP BFINSH ; B1200: MVI B,'1' CALL SEND1 MVI B,'2' JMP BFINSH ; B2400: MVI B,'2' CALL SEND1 MVI B,'4' ; BFINSH: CALL SEND1 MVI B,'0' CALL SEND1 ; BFIN1: MVI B,'0' CALL SEND1 ; BFIN2: MVI B,' ' CALL SEND1 MVI B,'b' CALL SEND1 MVI B,'p' CALL SEND1 MVI B,'s' CALL SEND1 MVI B,' ' CALL SEND1 MVI B,' ' JMP SEND1 ;..... ; ; ; Print message then exit to CP/M ; EXIT: POP D ; Get message address MVI C,PRINT ; Print message CALL BDOS CALL ILPRT ; Print CRLF before quitting DB CR,LF,0 ; LDA DRUSER ; Get original drive/user area back RAR RAR RAR RAR ANI 0FH ; Just look at the user area MOV E,A MVI C,SETUSR ; Restore original user area CALL BDOS ; LDA DRUSER ; Get the original drive/user back ANI 0FH ; Just look at the drive for now MOV E,A MVI C,SELDSK ; Restore original drive CALL BDOS ; LHLD STACK SPHL RET ;..... ; ; ; Inline print routine - prints string pointed to by stack until a zero ; is found. Returns to caller at the next address after the zero ter- ; minator. ; ILPRT: XTHL ; Save hl, get message address ; ILPLP: MOV A,M ; Get char CALL TYPE ; Output it INX H ; Point to next MOV A,M ; Test for end ORA A JNZ ILPLP XTHL ; Restore hl, ret address RET ; Return past the end of the message ;..... ; ; ; Output a character to the new file buffer - first, see if there is ; room in the buffer for this character. ; OUTCHR: PUSH PSW ; Store the character for now LHLD PTR ; Now get the buffer pointers XCHG LHLD ADR DAD D SHLD LAST XCHG POP PSW ; Get the character back STAX D ; Store the character LHLD PTR ; Get the buffer pointer INX H ; Increment them SHLD PTR ; Store the new pointer address RET ;..... ; ; ; Shows the line from memory, quits with a "LF" character ; SHOW: INX H ; Next character position in line MOV A,M ; Get the character CALL TYPE ; Send to CRT display MOV A,M ; Get the character again CPI LF ; Was it a line feed? JNZ SHOW ; If not, get next character LDA PGCNT ; increment line counter INR A STA PGCNT RET ; Otherwise finished this line ;..... ; ; ; Transfer is done - close destination file ; TDONE: MVI C,CLOSE LXI D,FILE CALL BDOS CALL ABORT LDA COUNT ; See if anything to display ORA A JZ NONE ; If not, say "NO NEW FILES" ; CALL ILPRT DB CR,0 LDA HDR ; Using a header? ORA A JZ TDONE2 ; If not skip header LDA SHOL ; Showing entire XMODEM.LOG? ORA A JZ TDONE2 ; If yes, don't bother with header ; ; ; Customizes header ; LDA OPTN ORA A JZ TDONE2 CALL ILPRT DB CR,'D/U Filename Size Speed ',0 LDA OPTN CPI 1 JZ TDONE1 CALL ILPRT DB ' Date Time Uploaded by',CR,LF,CR,LF,0 JMP TDONE2 ; TDONE1: CALL ILPRT DB 'Uploaded by Date',CR,LF,CR,LF,0 ; TDONE2: LHLD LAST ; Get address of last character stored CALL BACKUP ; Print first line in memory CALL SHOW ; TDONE3: CALL ABORT CALL BACKUP ; Need to back twice for rest of lines CALL BACKUP CALL SHOW JMP TDONE3 ; Keep going until all are printed ; TDONE4: CALL EXIT DB LF,CR,'[End of listing]','$' ;..... ; ; TOLONG: CALL ILPRT DB CR,'++ FILE TOO LONG, NEWEST ENTRIES LIKELY NOT ' DB 'SHOWN ++',CR,LF,CR,LF,0 JMP TDONE ; ;..... ; ; ; Send character in A register to console ; TYPE: PUSH B PUSH D PUSH H MOV E,A ; Character to E for CP/M MVI C,WRCON ; Write to console CALL BDOS POP H POP D POP B RET ;..... ; ; NONE: CALL EXIT DB CR,'++ NO NEW FILES ++','$' ; ; ; 'Declare' output file ; FILE: IF MBYE DB 0,'LOG ','S','Y'+80H,'S' ENDIF ; MBYE ; IF NOT MBYE DB 0,'XMODEM LOG' ENDIF ; NOT MBYE ; DB 0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0,0 ; ADR: DW BUFFER ; Address of buffer start LAST: DW 0 ; Address of last character in buffer PTR: DW 0 ; Pointer count for buffer ; COLUMN: DB 0 ; Column of XMODEM.LOG line COUNT: DB 0 DRUSER: DB 0 ; Original drive/user, for return LENGTH: DB 0 ; Maximum length of useable memory PRIVT: DB 0 ; Distinguishes "P" lines if shown STORE: DB 0 PGCNT: DB 0 ; For paging ; DS 100 ; Room for 50-level stack ; ; ; Set write buffer to even page boundry ; ORG ($+255)/256*256 ; BUFFER EQU $ ;write buffer starts here STACK EQU BUFFER-2 ; ; END START