home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
RCPM
/
COMSEC13.ASM
< prev
next >
Wrap
Assembly Source File
|
2000-06-30
|
16KB
|
726 lines
; COMSEC v1.3
; This program is similar in nature as the 'message service' for a
; SYSOP on a BBS. The main point is, that it can be used in the
; command line in CP/M. I was tired of having to re-enter the BBS
; just to leave a message because the SYSOP didn't answer on
; CHAT.
; Some of these routines were borrowed from CHAT. The origional
; author of CHAT was: Roderick Hart...
; The caller simply enters the program name or uses the option to
; immediately start without instructions. Using a ' D' after the
; name will directly enter it.
; It should also be noted that this program has NO provisions for
; anything less than CP/M 2.x...
;###############################################
; Written by:
;(except where noted)
; Version 1.0
; R. Kester
; JAN 05 84
; Version 1.1
; Minor changes, renumbered for me
; Version 1.2
; Some more minor changes...
; Version 1.3
; Re-did code so compatible with NUCHAT's..
;################################################
NO EQU 0
YES EQU 0FFH
STDCPM EQU YES ;Yes for 'standard' CP/M
ALTCPM EQU NO ;Yes for other type CP/M (TRS-80,etc)
IF STDCPM
BASE EQU 0
ENDIF
IF ALTCPM
BASE EQU 4200H
ENDIF
ORG BASE+100H
;Version 1.3
VER EQU 13 ;* Current version number
BDOS EQU BASE+5
FCB EQU 5CH
OPEN EQU 0FH
MAKE EQU 16H
READ EQU 14H
WRITE EQU 15H
CLOSE EQU 10H
SETDMA EQU 1AH
USR EQU 20H
DEFBUF EQU 80H
CR EQU 0DH
LF EQU 0AH
BELL EQU 07H
SPACE EQU 20H
SECT EQU 80H
DEL EQU 7FH
ABORT EQU 'A'-40H ;Abort program in message mode
FINIS EQU 'C'-40H ;Quit and save file (message)
EOF EQU 'Z'-40H ;End Of File
BACKUP EQU 'H'-40H ;Baskspace
JMP START ;Bypass
; NOTE: When specifying the drive code, enter the number
; corrosponding to the drive.
; i.e. 0=current drive
; 1=dirve 'A'
; 2=drive 'B'.....etc.
; 'MEMLIM' = This allows that number (MEMLIM) of bytes to be added
; starting at BUFF. BUFF is the area directly following this pro-
; gram where all received characters are stored, INCLUDING already
; existing messages (if any). i.e. If the value of MEMLIM were 50,
; then this program would only allow 50 bytes to be placed in mem-
; ory. It would then issue an error telling the user it is running
; low on memory and automatically 'close up shop'. It should be
; noted that, even if it does enter the error condition, it still
; includes the LASTCALR information. So this number should be used
; as a reference only.
; I.E. 20,000 = 20,000 BYTE MESSAGE FILE.
;* * * * * * USER MOD AREA * * * * * * *
;* Message limit (see note above) *
MEMLIM EQU 20000
;* Set YES for an RBBS system *
;* (use the LASTCALR file) *
RBBS EQU YES
;* # of characters per line *
LIMIT EQU 72
;* How many repeatative characters *
;* before tagging an error? *
TOMANY EQU LIMIT-8
;* User area you want messages in *
USER EQU 10
;* Drive for messages, put number here *
DFDRV EQU 1
;* Drive with LASTCALR on it *
CALLDR EQU 1
;* User area of LASTCALR *
CALLU EQU 0
;* File name created for messages *
;* spaces ||||||||||| =11 *
FNAME DB DFDRV,'MESSAGE CPM'
;* spaces ||||||||||| =11 *
; End of option selections *
;****************************************
; From here on, you shouldn't need to modify anything else...
IF RBBS
DBUF EQU 80H
BSIZE EQU 80H
CALLERFCB:
DB CALLDR,'LASTCALR ',0
DS 23
DB 0FFH
CALLERADR:DW DBUF
CALLERSIZ:EQU BSIZE
CALLERLEN:DW BSIZE
CALLERPTR:DS 2
ENDIF ;RBBS
START:
; Do the usual routine for the SP
LXI H,0
DAD SP
SHLD STACK
LXI SP,STACK
; Initialize direct CBIOS calls
LHLD 1
LXI D,3
DAD D
SHLD CSTAT+1 ;Con stat
DAD D
SHLD CIN+1 ;Con in
DAD D
SHLD COUT+1 ;Con out
; Get current user area and save it
MVI E,0FFH ;Code for GET
MVI C,USR
CALL BDOS ;Do it
STA OLDUSR ;Save it for return
;Get any potential options next
LDA DEFBUF+1
ORA A
JZ NNOP
LDA DEFBUF+2
STA OPT
NNOP:
IF RBBS
XRA A ;Zero A
STA CALLERFCB+12
STA CALLERFCB+32
LXI H,CALLERSIZ ;Get value
SHLD CALLERLEN
SHLD CALLERPTR
MVI E,CALLU ;Set area for LASTCALR
MVI C,USR
CALL BDOS
LXI D,CALLERFCB ;Point to filename
MVI C,OPEN
CALL BDOS
CPI YES ;Was it successful?
JNZ OPENOK ;Zero = No
CALL ILPRT
DB BELL,CR,LF,LF
DB 'ERROR --> LASTCALR file not found!...ABORTING'
DB CR,LF,LF,0
JMP LEAVE
OPENOK:
LXI D,DEFBUF ;Point to default buffer
MVI C,SETDMA ;Make new DMA addr
CALL BDOS
MVI C,READ ;Read in file @DMA
LXI D,CALLERFCB
CALL BDOS
ORI 0FFH ;Read OK?
JNZ ROK
CALL ILPRT
DB BELL,CR,LF,LF
DB 'ERROR -> Can''t read LASTCALR file!'
DB CR,LF,LF,0
JMP LEAVE
ROK:
CALL VEIW ;Set up name
MVI M,'$' ;Mark end
ENDIF ;RBBS
; Do sign-on
CALL ILPRT
DB CR,LF,LF
DB ' Computer Secretary v'
DB VER/10+'0','.',VER MOD 10+'0'
DB CR,LF,LF,0
; See if any requests are there
LDA OPT
CPI NO ;Any options?
JZ NONE ;No...
CPI 'D' ;Direct entry?
JZ DIRECT ;We saw a 'D'
; Otherwise give brief instructions
NONE:
CALL ILPRT
DB CR,LF
DB 'When the -: prompt appears, you may start entering'
DB CR,LF
DB 'your message. Hitting the RETURN key is not necessary'
DB CR,LF
DB 'for terminating lines. You may ABORT the process by'
DB CR,LF
DB 'entering a ^A. Use ^C for saving message.'
DB CR,LF
DB 'You may also make your life easier next time by:'
DB CR,LF,LF
DB 'A>progname D <-- use a ''D'' for direct entry'
DB CR,LF,LF
DB 0
; First, move the FNAME into the FCB
DIRECT:
MVI B,12 ;Number of bytes to move
LXI H,FCB ;The 'to' place
LXI D,FNAME ;The 'what to move' name
LOOP:
LDAX D ;Get the byte
MOV M,A ;Get the 'what' byte
INX H ;Bump the pointer
INX D ;Bump the 'getter'
DCR B ;Decrement the counter
JNZ LOOP ;If B<>0 then keep chuggin'
CALL CLRFCB ;Clear certain extensions
; And set the area for the messages...
MVI E,USER ;Get ready to set the
MVI C,USR ; user are desired
CALL BDOS ;Do it.
LXI D,FCB ;Point to the filename
MVI C,OPEN ;Get ready to open
CALL BDOS ;the file pointed by DE
CPI YES ;Was it successful?
JZ MAKEIT ;Zero = make it the first time
; Now read in the current contents...
LXI D,BUFF ;Point to buffer
RLOOP:
MVI C,SETDMA
PUSH D ;Save previous DMA addr.
CALL BDOS
LXI D,FCB ;Point to filename
MVI C,READ ;Read it in
CALL BDOS
POP D
ORA A ;Find out DIR code
JNZ FINISHED ;Zero = not finished
LXI H,80H ;Value of 1 sector
DAD D ;HL has new DMA addr.
XCHG ;Now DE has
JMP RLOOP
CLRFCB:
XRA A ;Zero A
STA FCB+12
STA FCB+32
RET
; We finished reading the file in to buffer
FINISHED:
XCHG ;Get the last DMA for a double check
SHLD POINTR
CALL CLRFCB ;Clear the record info for writing
CALL SEARCH ;Find the EOF mark and cancel it.
; and then reset the POINTR.
BEGIN:
IF RBBS
CALL FIRSTNM ;Get & print callers name
ENDIF ;RBBS
CALL ILPRT
DB BELL,CR,LF
DB ' - ^A aborts - ^C saves message'
DB CR,LF,LF
DB '-: '
DB 0
READIT:
CALL TESTMEM ;Check memory limit
CALL CIN ;Get a byte typed by the user
CPI FINIS ;A ^C?
JZ QUIT ;Yes?, then tidy up
CPI ABORT ;Change their mind?
JZ STOP ;Yes?, then don't tidy up
CPI CR ;A return?
JZ CRLF ;Yes?, do the dirty work
CPI BACKUP ;A backspace?
JZ BACK ;Do what it requires
CPI DEL
JZ BACK
CPI ' ' ;A space?
JC READIT ;If it equals a value below, then loop
CALL PUTNMEM ;Slip it in memory
PUSH PSW ;Save 'A'
MOV C,A ;Swap it for output
CALL COUT ;Send it to them
POP B ;Get 'A' into 'B' now
LDA COUNT ;How far we gone on the screen?
INR A ;Bump it
STA COUNT ;Save it
CPI LIMIT ;Too many characters yet?
JZ CRLF ;Yep
CPI LIMIT-8 ;Near the limit?
JC READIT ;Nope
MOV A,B ;Find out if we can
CPI ' ' ; help'm out and do a
JNZ READIT ; return for them...
CRLF:
CALL ILPRT ;...we could!
DB CR,LF
DB '-: '
DB 0
XRA A ;Reset the counter
STA COUNT
MVI A,CR ;Load a RETURN
CALL PUTNMEM
MVI A,LF ;Load a LINE FEED
CALL PUTNMEM
JMP READIT ;Do it all again
BACK:
LDA COUNT ;Get the counter
DCR A ;Sub one for a backspace
JM READIT ;Already at 0?
STA COUNT ;Then save it
CALL ILPRT
DB BACKUP,' ',BACKUP,0
LHLD POINTR ;Get pointer value
MVI A,L ;If it is already
ORA H ; a zero then
JZ READIT ; skip the rest
DCX H ;Sub one for backup
SHLD POINTR ;Save it
JMP READIT ;Go back and do some more
; Inline print routine using direct I/O
ILPRT:
XTHL ;Swap SP/HL
ILPLP:
MOV C,M ;'C' = ->HL
PUSH H
CALL COUT ;Send it to the console
POP H
INX H ;Bump the char. pointer
MOV A,M ;'A' = ->(HL)
ORA A ;Is it a null?
JNZ ILPLP ;Nope, do some more
XTHL ;Yep, swap HL/SP
RET
IF RBBS
;Enter here to display callers name to CRT...
FIRSTNM:
CALL ILPRT
DB 'Sorry I wasn''t around ',0
LXI H,DEFBUF ;Point to area
HAGA:
MOV A,M ;Get byte
CPI '$' ;See if end
JZ ALM ;Yes...
PUSH H ;Else, save HL
MOV C,A ;Get byte to send
CALL COUT ;Send it to CRT
POP H ;Get HL back
INX H ;Bump it
JMP HAGA ;Loop..
ALM:
CALL ILPRT
DB '....',CR,LF,LF,0 ;Send this for looks
RET
;Enter this routine to set-up the name to be printed
;in the file, Replaces the comma with a space. Puts
;it the default buffer...
VEIW:
LXI H,DEFBUF ;Point to defualt buffer
DLOP:
MOV A,M ;Get a byte
CPI EOF ;End of file
RZ ;Yes..or
CPI CR ; found a CR?
RZ ;Yes...
ALOOP:
CPI ',' ;Then check for this
JNZ BLOP ;No...
MVI A,' ' ;Then make it a space
BLOOP:
MOV M,A ;Put it in memory
BLOP:
INX H ;Bump pointer
JMP DLOP ;Loop...
ENDIF ;RBBS
;Message for SYSOP if too many chars. in arow.
TOMSG: DB CR,LF,LF,'This person possibly tried to fool you!',CR,LF,'$'
;Enter here when we got too many of the same character in a row.
TOERR:
CALL ILPRT
DB BELL,CR,LF,LF
DB 'ERROR -> Too many similar characters, ABORTING!'
DB CR,LF,LF,0
LHLD ORNPTR ;Get value before anything was entered
SHLD POINTR ;Make that the current value
LXI D,TOMSG ;Enter a msg. so SYSOP nows why
CALL PLOOP ; nothing was entered
QUIT:
MVI A,CR ;Put some area in for readibility
CALL PUTNMEM
MVI A,LF
CALL PUTNMEM
CALL PUTNMEM
IF NOT RBBS
JMP ALMOST
ENDIF ;NOT RBBS
IF RBBS
CALL CALLGET ;Put name into file
JMP ALMOST
;Enter here to place callers name into file..
CALLGET:
LXI D,DEFBUF
HLOOP:
LDAX D ;Get byte
CPI '$' ;End?
RZ ;Yes..
PUSH D ;Then save DE
CALL PUTNMEM ;Get byte=>DE put in file by (HL)
POP D ;Get DE back
INX D ;Bump it
JMP HLOOP ;Loop...
ENDIF ;RBBS
; Call this routine each time we enter a byte into the buffer
; and keep track of twits...
PUTNMEM:
STA TEMP ;Save A for the following
LHLD POINTR ;Get current value
MOV B,A ;Save it
MOV M,A ;Slip in byte
INX H ;Bump the pointer
SHLD POINTR ;Save it
LHLD POINTR ;Get it back
DCX H ;Decrement it
DCX H ; again
MOV A,M ;Get byte
CMP B ;The same as B?
JZ SETNOT ;Yep..
CPI CR ; ?
JZ SETNOT ;Yep..
CPI LF ; ?
JZ SETNOT ;Yes?, do something about it
XRA A ;No?, then
STA MNYCNT ; reset count
LDA TEMP ;Get A back
RET
;Enter here when we find the same character typed twice in a row.
;And exit if too many of them, and keep the caller's name.
SETNOT:
LDA MNYCNT ;Get count
INR A ;Bump it
STA MNYCNT ;Save new count
CPI TOMANY ;Too many of them?
JZ TOERR ;Yes?, then error exit
LDA TEMP ;Get A back
RET
; Test memory limit... if we are there, then quit
TESTMEM:
LHLD MEMS ;The number not to exceed
XCHG ;Swap
LHLD POINTR ;The number to compare to
MOV A,H ;Put MS part in A
CMP D
RC ;Ok, if carry
MOV A,L ;Else do the same
CMP E
RC ;Ok, if carry
;No carry so we are over exteneded...
CALL ILPRT ;Then print error message
DB BELL,CR,LF,LF
DB 'SORRY -> Ending things, running low on memory!'
DB CR,LF
DB 'Please try again another time...'
DB CR,LF,LF,0
JMP QUIT ;Close up shop
MEMS: DW BUFF+MEMLIM ;Max. value not to exceed
; Put some sort of marking for the next message
; when being typed out.
; End of message delimmiter.
ENDING: DB CR,LF,LF,'+ + + + + + + + + + + + + + + +',CR,LF,LF,'$'
ALMOST:
LXI D,ENDING ;Put the above line in the file
CALL PLOOP ; for readibility
JMP GONE
;Used elsewhere...
PLOOP:
LDAX D
CPI '$'
RZ
CALL PUTNMEM
INX D
JMP PLOOP
GONE:
MVI A,EOF ;Get EOF mark
CALL PUTNMEM
; Change the user area for the message file
MVI E,USER
MVI C,USR
CALL BDOS
LXI D,BUFF ;Beginning of DMA
PUSH D ;Save it
WLOOP:
POP D ;Get previous push into DE
PUSH D ;Save on the stack
MVI C,SETDMA ;Set the DMA to
CALL BDOS ;the addr. in DE
LXI D,FCB ;Point to filename
MVI C,WRITE ;Write to it
CALL BDOS
CPI NO ;Successful?
JNZ WEXIT ;Zero = yes
POP H ;Get the past DMA addr.
LXI D,SECT ;One more sector
DAD D ; is added to the value
PUSH H ;Save the next DMA addr.
MOV A,H ;Get the high byte
CMA ;1's compliment
MOV D,A ;Save that in D
MOV A,L ;Get the low byte
CMA ;1's compliment
MOV E,A ;Save that in E
INX D ;= inverted current DMA addr.+1
LHLD POINTR ;Get # of bytes that were typed
DAD D ;Effectively -> NEW - CURRENT =
; # of bytes left to write in HL
MOV A,H ;Get the MS value in A
INR A ;Bump it
ANA A ;Set any flags? (a -1?)
JNZ WLOOP ;No, then we have more to write.
POP H ;Clean the stack
JMP EXIT
WEXIT:
CALL ILPRT
DB CR,LF,LF,BELL
DB 'ERROR --> Can''t write file, ABORTING!'
DB CR,LF,LF,0
JMP LEAVE ;Leave and do nothing
EXIT:
LXI D,FCB ;Point to filename
MVI C,CLOSE ;And close it
CALL BDOS
CPI YES ;Successful?
JNZ LEAVE ;Zero = No
CALL ILPRT
DB CR,LF,LF,BELL
DB 'ERROR --> Can''t close file, ABORTING!'
DB CR,LF,LF,0
LEAVE:
MVI C,SETDMA ;Re-set the DMA
LXI D,DEFBUF ; so we don't
CALL BDOS ; mess up.
LDA OLDUSR ;Get origional
MOV E,A ; user area and
MVI C,USR ; return us to
CALL BDOS ; there.
LHLD STACK ;Get origional SP
SPHL ; for 'soft' return
RET
STOP:
CALL ILPRT
DB CR,LF,LF
DB '* * * ABORTED! - Nothing saved * * *'
DB CR,LF,LF,0
JMP LEAVE
; Create the file
MAKEIT:
CALL ILPRT
DB CR,LF
DB 'Creating file...'
DB CR,LF,LF,0
LXI D,FCB ;We had to create it new
MVI C,MAKE
CALL BDOS
CPI YES ;successful?
LXI H,BUFF ;If we goto BEGIN....
SHLD POINTR
JNZ BEGIN ;Zero = No
CALL ILPRT
DB CR,LF,LF,BELL
DB 'ERROR --> No directory space or trouble opening.'
DB CR,LF,LF
DB 'Please try again another time....'
DB CR,LF,LF,0
JMP EXIT
;Search the current file and blank out the EOF mark...
SEARCH:
LXI D,BUFF ;Point to beginning
LHLD POINTR ;Get current position
SLOOP:
LDAX D ;Move byte into A
CPI EOF ;Was it the EOF?
JZ NULLIT ;Yep?, the zero it
INX D ;No?, then keep searching
DCX H ;Decrement the pointer
MOV A,H ;Find out if we have no
ORA L ; more positions
JZ NULLERR ;Just used for a double check
JMP SLOOP ;Else, check some more
NULLIT:
XRA A ;Zero A
XCHG ;Get position in HL
MOV M,A ;Put a '0' there
SHLD POINTR ;Save the area where our new
DCX H ;Save for later if we
SHLD ORNPTR ; need it...
RET ; buffer starts
; Enter here if we did not find an EOF mark in the available
; number of positions (double check)
NULLERR:
CALL ILPRT
DB BELL,CR,LF,LF
DB 'The validity of the file might be questioned'
DB CR,LF
DB 'Did NOT find the EOF, and should have!'
DB CR,LF,LF,0
RET
CSTAT: JMP $-$ ;Set upon entry
CIN: JMP $-$ ; " " "
COUT: JMP $-$ ; " " "
COUNT: DB 0
OPT: DB NO
TEMP: DS 1
MNYCNT: DS 1
OLDUSR: DS 1
POINTR: DS 2
ORNPTR: DS 2
DS 64 ;32 level stack
STACK:
DS 2 ;Storge for incoming stack
BUFF EQU $ ;Message buffer starts here
END