;CBBS V3.5.0 	CBBSOPER.ASM - OPERATOR FUNCTIONS
;12/03/81 15:42:22		(EXCEPT MESSAGE KILL)
;
;	LINKS TO CBBSKILL
;
;	O O O	O O O	O O O	O O O
;	O   O	O   O	O	O   O
; CBBS	O   O	O O O	O O	O O O	.ASM
;	O   O	O	O	O O
;	O O O	O	O O O	O   O
;
;
;MODS LOG: (THRU 3.2 MOVED TO "HISTORY")
;
;====> HISTORICAL COMMENTS SINCE 3.3 TO "HISTORY.033"
;
;-----> VALIDATE CE FUNCTION
;
;FORMAT FILENAME
;11/11/78 NOTE SIGNIFICANT MODS TO THIS
;	ROUTINE, TO HANDLE A: AND B: NAMES
;
CEFNC	XRA	A
	STA	CEFCB	;SO STAT WILL GO TO A:
;
;PUT "R" IN "WHERE FROM" IN CASE "NAME" COMMAND,
;I.E. RE-LOG IN.
;
	LXI	H,SUBJ	;WHERE 'CITY' STORED
	MVI	M,'R'
	INX	H
	MVI	M,','
	INX	H
	MVI	M,CR
;
	LXI	H,ANSWER
;
;SCAN FOR ' ' AFTER COMMAND
;
CESKB	MOV	A,M
	CPI	CR	;NO ' ' (E.G. STAT CMD)
	JZ	CECR	;	YES
	CPI	' '
	INX	H
	JNZ	CESKB
;
;POINTING TO FILENAME OR DISK:FILENAME (OR END OF LINE)
;
	XRA	A	;DEFAULT TO
	STA	CEFCB	;	LOGGED IN DISK
	MOV	A,M	;JUST "DIR "?	
	CPI	CR
	JZ	CECR
	INX	H	;CHECK FOR ':'
	MOV	A,M
	DCX	H
	CPI	':'	;DISK REQUESTED?
	JNZ	CECR	;	NO
;PUT DISK INTO FCB
	MOV	A,M	;GET DISK
	SUI	'A'-1	;MAKE BINARY (A=1, ETC)
	STA	CEFCB	;STORE IN FCB
	INX	H	;SKIP TO ':'
	INX	H	;SKIP ':'
;POINTING TO FILENAME
CECR	MVI	B,8	;FILENAME LEN
	LXI	D,CEFN	;POINT TO FILENAME
	CALL	CEFMN	;FORMAT NAME
	MVI	B,3	;FILETYPE LEN
	LXI	D,CEFT	;POINT TO FILETYPE
	CALL	CEFMN	;FORMAT TYPE
;
;FOR CHAR STRING MATCH IN FILE TYPE COMMAND,
;SAVE A POINTER TO THE COMMA, AND SAVE THE
;LAST CHAR SCANNED.  IF A COMMA, THEN WE
;ARE DOING STRING MATCH IN THE FILE TYPING.
;
	MOV	A,M	;GET COMMA (MAYBE)
	STA	STRFLG	;SAVE CHAR
	INX	H	;SKIP COMMA
	SHLD	STRPTR	;SAVE POINTER (MAYBE)
;
;LOOK UP THE COMMAND
;
	LXI	H,CEFTAB ;FUNCTION TABLE
	CALL	CELOOK
	JMP	WHATM
;
;====>	LOOK UP COMMAND
;	HL POINTS TO TABLE.  RETURNS ONLY IF NOT FOUND
;
CELOOK	LXI	D,ANSWER ;COMMAND
	MVI	B,4
CELKLP	LDAX	D
	CMP	M
	JNZ	CELNO
	INX	D
	INX	H
	DCR	B
	JNZ	CELKLP
;
;FOUND, EXECUTE IT
;
CELGOT	MOV	E,M	;GET LO ADDR
	INX	H
	MOV	D,M	;GET HI
	POP	H	;DUMP RETURN ADDR
	XCHG
	PCHL		;TO COMMAND
;
;NOT FOUND - SKIP IT, TRY NEXT
;
CELNO	INX	H
	DCR	B
	JNZ	CELNO
	INX	H	;SKIP
	INX	H	;	ADDR
	MOV	A,M
	ORA	A
	RZ		;NOT FOUND
	JMP	CELOOK
;
;-----> TYPE A FILE
;
CETYPE	LXI	H,CEFCB
	LDA	ANSWER+4	;%07/11/81 MOD
	CPI	'H'
	JZ	CETFH
	CPI	'K'
	JZ	CETFK
	CALL	TYPEF
	JMP	FUNCT
;
;TYPE FILE, BUT ONLY LINES WITH "]"
;
CETFH	CALL	TYPEFH
	JMP	FUNCT
;
;TYPE FILE, LINES WITH ], AND THE NEXT 2 LINES
;
CETFK	CALL	TYPEFK
	JMP	FUNCT
;
;-----> ERASE A FILE
;
CEERA	LXI	H,CEFN
	MOV	A,M
	CPI	'?'
	JZ	CENOTF
	DCX	H	;BACK TO DISK #
	CALL	SETRD	;SETUP
	JC	CENOTF	;NOT FOUND
	LXI	D,FCB
	MVI	C,ERASE
	CALL	BDOS
	CALL	ILPRT
	DB	'++ERASED',0
	JMP	FUNCT
;
;-----> DIR FUNCTION
;
CEDIR	LXI	H,CEFCB
	LXI	D,FCB
	MVI	B,12
	CALL	MOVE	;SET UP NAME
	MVI	A,'?'	;FIND ALL
	STA	FCBEXT	;	EXTENTS
01; DELETED FOLLOWING 2 LINES
01;	CALL	ILPRT
01;	DB	'--NAME--TYP X SEC',CR,LF,0
	LXI	H,'  '	;INIT #
	SHLD	CEDIRN	;	OF FILES
	MVI	A,'0'
	STA	CEDIRN+2
03;MODS:
	LDA	FCB+1	;IF FCB
	CPI	' '	;	IS ' '
	JNZ	CENQ	;	THEN
	LXI	H,FCB+1	;	MAKE
	MVI	A,'?'	;	IT
	MVI	B,11	;	ALL
CEDIRQ	MOV	M,A	;	'?'
	INX	H
	DCR	B
	JNZ	CEDIRQ
;
CENQ	MVI	C,SRCHF	;SEARCH FIRST
03;END
	JMP	CEDIRF
;
CEDIRL	MVI	C,SRCHN ;SEARCH NEXT
CEDIRF	LXI	D,FCB
	CALL	BDOS	;ANY?
	INR	A
	JZ	CEDIRE	;END
	DCR	A
	ANI	3	;ISOLATE # IN SECTOR
	ADD	A
	ADD	A
	ADD	A	;MULTIPLY BY 32
	ADD	A
	ADD	A
	ADI	81H	;LOC'N IN BUFFER
	MOV	L,A
	MVI	H,0
	PUSH	H	;SAVE NAME POINTER
	LXI	D,11
	DAD	D	;POINT TO EXT
	MOV	A,M	;GET EXTENT
	MVI	M,' '	;STORE A SPACE
	ADI	'0'	;GET EXTENT
	INX	H
	MOV	M,A	;SAVE EXTENT
	INX	H
	MVI	M,0	;ZERO AS END OF NAME
	POP	H	;RESTORE NAME POINTER
;DON'T PRINT DETAIL IF COMMAND WAS 'DIRN'
	LDA	ANSWER+3
	CPI	'N'
	JZ	CEDNOP	;NO PRINT
	CALL	TYPEM0	;TYPE NAME
	CALL	SPACE
	MOV	A,M	;GET REC COUNT
	CALL	PRDEC	;PRINT IN DECIMAL
03;MODS:
cedire	LDA	TABCOL
	CPI	45
	JNC	CEDCRLF
	CALL	SPACE
	CALL	SPACE
	JMP	CEDNOP
CEDCRLF	CALL	CRLF
CEDNOP	LXI	H,CEDIRN+2 ;IGINALLY LOGGED IN DISK
;
	POP	D
	MVI	C,LGINDK
	CALL	BDOS
	JMP	FUNCT
03;END
;
;---->	'NOTE' FUNCTION - WRITES NOTES TO 'CRLF
03	ORA	A	;	ONLY IF NOT
03	CNZ	CRLF	;	IN COLUMN 0
	LDA	ANSWER+3	;DIRN?
	CPI	'N'
	JZ	CEDIRI
	LDA	CEDIRN+1
	CPI	' '
	JNZ	CEDIRI
	LDA	CEDIRN+2
	CPI	'4'
	JC	FUNCT	;ONLY 0-3, DON'T TELL HOW MANY
CEDIRI	CALL	ILPRT
CEDIRN	DB	'  0'	;MODIFIED
	DB	' Files',0
	JMP	FUNCT
;
	IF	BULL
;
;-----> ADD MESSAGE TO BULLETIN FILE
;
CEBULL	LXI	H,BULFL	;POINT TO FILENAME
	CALL	SETRD	;SEE IF IT EXISTS
	JC	CEBNF	;NO FILE EXISTS
CEBQ	CALL	GETVAR
	DB	'Y/N: WANT TO ERASE PREVIOUS '
	DB	'BULLETIN(S)',0
	DW	ANSWER
02	DW	00	;HELP MSG #
	DB	1	;LEN
	LDA	ANSWER
	CPI	'N'
	JZ	CEBNF
	CPI	'Y'
	JNZ	CEBQ	;RE-ASK
	LXI	D,FCB
	MVI	C,ERASE
	CALL	BDOS
CEBNF	LXI	H,BULFL	;POINT TO FILENAME
	CALL	EXTEND	;EXTEND THE FILE
	LXI	H,BULLIN ;'---- BULLETIN----'
	CALL	WRLINE
	CALL	ILPRT
	DB	CR,LF
	DB	'ENTER BULLETIN LINE, C/R WHEN DONE.'
	DB	CR,LF,'FOR A BLANK LINE,'
	DB	'TYPE 1 SPACE, THEN C/R'
	DB	CR,LF,0
;SHOW UPDATING DISK
	MVI	A,1
	STA	DKUPSW
	STA	CTLKSW	;ALSO DISABLE CTL-K
CEBULI	CALL	GETVARN
	DB	0	;NO MSG
	DW	ANSWER
02	DW	00	;HELP MSG #
	DB	60	;LEN
	LDA	ANSWER
	CPI	CR
	JZ	CEBEND	;END OF BULLETIN
	LXI	H,ANSWER
	CALL	WRLINE
	JMP	CEBULI
;
;END OF BULLETIN
;
CEBEND	LXI	H,BULLIN
	CALL	WRLINE
;PUT A ']' (END OF QUESTION) IN THE FILE, SO IF
;THE USER CONTROL-C'S THE BULLETIN, IT WILL SKIP
;TO THE NEXT BULLETIN MESSAGE (IF THERE IS ONE)
	MVI	A,']'
	CALL	WRBYTE
	CALL	WRCRLF
	CALL	WREOF	;EOF, CLOSE FILE
	JMP	FUNCT
	ENDIF
;
;---->	STAT
03;MODS		REWRITTEN TO BE "UNIVERSAL"
;
;STAT FUNCTION - DETERMINES SIZE OF ALL LOGGED IN DISKS
;		CP/M 1.4 AND 2.2 COMPATIBLE.
;
CESTAT	MVI	C,INQDISK
	CALL	BDOS	;GET, AND
	PUSH	H	;	SAVE CURRENT DISK
	MVI	C,GETLGIN
	CALL	BDOS	;FIND WHICH DISKS LOGGED IN
	MOV	C,A	;C=LOGIN VECTOR
	MVI	B,1	;B=NEXT DISK TO TRY
	MVI	D,'A'	;CURRENT DISK BEING TRIED
CESTDK	PUSH	B	;SAVE DISK, ETC
	PUSH	D
	MOV	A,C	;GET LOGIN VECTOR
	ANA	B	;TEST FOR 1 DISK
	JZ	CESTNLI	;NOT LOGGED IN
;SELECT THE DISK
	MOV	A,D	;GET ASCII
	CALL	TYPE	;TYPE IT
	MVI	A,':'	;THEN ':'
	CALL	TYPE
	MOV	A,D
	SUI	'A'	;MAKE IT ACCEPTABLE TO BDOS
	MOV	E,A
	MVI	C,LGINDK	;LOGIN THE DISK
	CALL	BDOS	;LOG IN THE DISK
;
;GET THE SIZE OF THE DISK
;
	MVI	C,GETVERS
	CALL	BDOS	;GET VERSION
	MOV	A,L
	ORA	A
	JNZ	CEST22	;IT IS 2.2
;
;THIS IS 1.4, SO GET PARM BLOCK FROM THE FRONT OF BDOS
;
	LHLD	BDOS+1	;GET ADDR
	LXI	D,36H	;OFFSET TO PARM
	DAD	D
	MOV	A,M	;GET BLOCK SHIFT FACTOR
	INX	H
	INX	H
	MOV	E,M	;GET DISK SIZE
	MVI	D,0
	JMP	CESTCAL
;
CEST22	MVI	C,GETPARM
	CALL	BDOS	;GET DISK PARM ADDR
	INX	H
	INX	H
	MOV	A,M
	INX	H
	INX	H
	INX	H
	MOV	E,M
	INX	H
	MOV	D,M
CESTCAL	XCHG
	INX	H	;FUDGE HL TO # OF BITS IN MAP
	PUSH	PSW	;SAVE ALLOCATION BLOCK SIZE
	PUSH	H	;SAVE # BITS
	MVI	C,INQALC
	CALL	BDOS	;GET ALLOCATION
	POP	D	;GET BIT MAP COUNT
	LXI	B,0	;INIT # K FREE
CESTB80	MVI	A,80H	;INIT MASK
CESTBIT	PUSH	PSW	;SAVE MASK
	ANA	M	;FREE?
	JNZ	CESTNB	;NO BIT
	INX	B	;COUNT THE BIT
CESTNB	DCX	D	;COUNT DOWN # BITS
	MOV	A,D
	ORA	E
	JZ	CESTASC	;DONE, COMPUTE IN ASCII
	POP	PSW	;GET MASK
	ORA	A	;NO CARRY
	RAR		;RIGHT 1 BIT,
	JNC	CESTBIT	;LOOP IF SAME BYTE
	INX	H	;TO NEXT BYTE
	JMP	CESTB80
;
;DONE, BC = #K FREE, COMPUTE IN ASCII
;
CESTASC	POP	PSW	;DUMP THE BIT MASK
	LXI	H,CESTFRE
	MVI	A,' '
	MOV	M,A
	INX	H
	MOV	M,A
	INX	H
	MOV	M,A
	INX	H
	MVI	M,'0'	;IN CASE '0' K FREE
;
;NOW, MULTIPLY THE # OF BITS THAT WERE 0,
;	BY THE # OF K PER BIT
;
	POP	PSW	;GET BLOCK SHIFT
	MOV	D,B
	MOV	E,C	;MOVE COUNT TO DE
	XCHG		;THEN TO HL
	SUI	3	;IS IT 1K?
	JZ	CESTASB	;YES
CESTINK	DAD	H	;DOUBLE # OF BITS FREE
	DCR	A	;COUNT DOWN
	JNZ	CESTINK
CESTASB	XCHG
CESTASL	MOV	A,D	;DOWN TO
	ORA	E	;	0 LEFT?
	JZ	CESTPRT	;	YES, PRINT IT
	PUSH	H	;SAVE POINTER
	CALL	ADD1	;ADD 1 IN ASCII
	DCX	D	;DCR COUNT
	POP	H
	JMP	CESTASL
;
CESTPRT	CALL	ILPRT
CESTFRE	DB	'    K Free',0DH,0AH,0
;
;DISK NOT LOGGED IN, OR DONE PROCESSING.  TRY NEXT ONE
;
CESTNLI	POP	D
	POP	B
	INR	D	;BUMP PRINTABLE DISK
	MOV	A,B	;GET MASK
	ADD	A	;SHIFT LEFT
	MOV	B,A
	JNC	CESTDK	;PROCESS NEXT DISK
;
;RESTORE ORIGINALLY LOGGED IN DISK
;
	POP	D
	MVI	C,LGINDK
	CALL	BDOS
	JMP	FUNCT
03;END
;
;---->	'NOTE' FUNCTION - WRITES NOTES TO 'NOTES' FILE
;	WHICH ARE THEN TYPED VIA 'TYPE NOTES' COMMAND
;	AND ERASED VIA 'ERA NOTES' COMMAND
;
CENOTE	if	twitck
	call 	twitst
	jz	whatm	;don't let twits
	lda	twitsw	;enter memos
	ora	a
	jnz	whatm
	mvi	a,1
	sta	dkupsw
	sta	ctlksw	;no control k allowed
	endif
;
	LXI	H,NOTEFL ;POINT TO FILENAME
	CALL	EXTEND	;EXTEND (OR CREATE)
	MVI	A,']'
	CALL	WRBYTE
;
	LDA	ANSWER+4 ;IS THIS "NOTEN"
	CPI	'N'	;	I.E. NOTES
	JZ	CENOTEN	;	WITHOUT HEADER?
;
	LXI	H,COMFRM ;WRITE 'FROM:',
	CALL	WRVAR
	LXI	H,FNAME
	CALL	WRVARC	;FIRST NAME ","
;
 IF CLOCK
	CALL	WRTIME
 ENDIF
CENOTEN	CALL	WRCRLF
;
CENLP	CALL	GETVARN	;07/19/81 FORMERLY GETVAR
	DB	':',0	;07/11/81 FORMERLY HAD CR,LF
	DW	ANSWER	;READ IN HERE
02	DW	0	;HELP MSG #
	DB	60	;LINE LENGTH
	LDA	ANSWER	;END?
	CPI	CR
	JZ	CENEND	;YES, END
	LXI	H,ANSWER
	CALL	WRLINE	;WRITE LINE TO DISK
	JMP	CENLP	;LOOP UNTIL C/R ENTERED
;
;END OF CE NOTE FUNCTION - CLOSE FILE
;
CENEND	CALL	WREOF	;CLOSE
	JMP	FUNCT
03;MODS:
;
;====>	HOLD	COMMAND PREVENTS PHONE HANGUP
;
HOLD	LDA	HOLDFLG
	XRI	1
	STA	HOLDFLG
	JNZ	HOLDNO
	CALL	ILPRT
	DB	'Will',0
	JMP	HOLDMSG
;
HOLDNO	CALL	ILPRT
	DB	'Won''t',0
HOLDMSG	CALL	ILPRT
	DB	' time out',0
	JMP	FUNCT
03;END
;
;---->	DUMP COMMAND - USE CTL-K TO ABORT
;
CEDUMP	LXI	D,CEFN	;TO ASCII HEX
	CALL	RDHEX	;TO HL
;
;DUMP A LINE AT A TIME, ABORT ON CTL-K
;
CEDULN	MOV	A,H
	CALL	HEX
	MOV	A,L
	CALL	HEXB
	PUSH	H
CEDUNHC	MOV	A,M
	INX	H
	CALL	HEX
	CALL	CTLCKS
	JZ	FUNCT
	MOV	A,L
	ANI	3
	CZ	SPACE
	MOV	A,L
	ANI	0FH
	JNZ	CEDUNHC
	POP	H
	CALL	CEDUAST
CEDUASC	MOV	A,M
	ani	7fh	;mask off bit 7
	CPI	' '
	JC	CEDUPER
	CPI	7FH
	JC	CEDUNP
CEDUPER	MVI	A,'.'	;NON PRINTABLE
CEDUNP	CALL	TYPE
	CALL	CTLCKS
	JZ	FUNCT
	INX	H
	MOV	A,L
	ANI	0FH
	JNZ	CEDUASC
	CALL	CEDUAST
	CALL	CRLF
	JMP	CEDULN
;
CEDUAST	MVI	A,'*'
	JMP	TYPE
;
;====>	PRINT	ROUTINE, CAUSES TYPING TO ECHO TO LIST
;
CEPRINT	LDA	PRINTSW
	XRI	1
	STA	PRINTSW
	JZ	CEPRNO
	CALL	ILPRT
	DB	'On',0
	JMP	FUNCT
;
CEPRNO	CALL	ILPRT
	DB	'OFF',0
	JMP	FUNCT
;
;---->	ENTR COMMAND - ENTER A BYTE INTO MEMORY
;
;	ENTR ADDR.DATA, DATA = 1 BYTE ONLY
;
CEENTR 	LXI	D,CEFT
	CALL	RDHEX	;GET DATA
	MOV	B,L	;SAVE IT
	LXI	D,CEFN	;TO ADDR
	CALL	RDHEX
	MOV	A,M	;GET OLD VALUE
	CALL	HEX
	MOV	M,B	;STORE NEW
	JMP	FUNCT
;
;====>	CESLOW
;		TO SLOW DOWN TYPING
;		WHEN TESTING CBBS LOCALLY
;
CESLOW	LDA	TYPDLY+2 ;GET TYPING DELAY
	ADI	8
	ANI	18H
	STA	TYPDLY+2
	JMP	FUNCT
;
;HEX READ ROUTINE, DE POINTS TO ASCII.
;TERMINATES WITH ' ' OR CR.
;
RDHEX	LXI	H,0	;INIT ADDR
RDHI	LDAX	D
	INX	D
	CPI	' '	;END?
	RZ		;START DUMPING
	CPI	CR
	RZ
	CPI	'0'	;CONV ASCII TO HEX
	JC	WHATM		
	CPI	'9'+1
	JC	RDHNUM
	CPI	'A'
	JC	WHATM
	CPI	'F'+1
	JNC	WHATM
	SUI	7
RDHNUM	SUI	'0'
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	ADD	L
	MOV	L,A
	JMP	RDHI
;
;FILE NOT FOUND
;
CENOTF	CALL	ILPRT
	DB	'No: ',0
	LXI	H,CEFN
	MVI	B,0
	CALL	TYPEM
	JMP	FUNCT
;
;FORMAT NAME - PAD W/SPACES. LEN IN B
;
CEFMN	MOV	A,M
	CPI	CR	;END?
	JZ	CEFEND
	CPI	','	;START OF STRING?
	JZ	CEFEND
	INX	H
	CPI	'.'
	JZ	CEFEND
	CPI	'*'
	JZ	CEFQM	;FILL W/'?'
	STAX	D
	INX	D
	DCR	B
	JNZ	CEFMN
	MOV	A,M	;AT '.'?
	CPI	'.'
	RNZ		;NO
	INX	H	;SKIP '.'
	RET
;
;END OF INPUT FIELD, PAD W/' '
;
CEFEND	MVI	A,' '
	STAX	D
	INX	D
	DCR	B
	JNZ	CEFEND
	RET
;
;GOT "*", PAD WITH '?'
;
CEFQM	MVI	A,'?'
	STAX	D
	INX	D
	DCR	B
	JNZ	CEFQM
	MOV	A,M	;AT '.'?
	CPI	'.'
	RNZ
	INX	H
	RET
;
;
;-----> WORK AREA FOR CE FUNCTIONS
;
CEFCB	DS	1	;DISK (A=1, ETC)
CEFN	DS	8	;FILENAME
CEFT	DS	3	;FILETYPE
	DB	0	;END OF NAME, FOR PRINTING
;
	IF	BULL
CEBULPW	DB	'BULOK'	;BULLETIN FUNCTION PASSWORD
CEBULPL	EQU	$-CEBULPW ;PASSWORD LENGTH
	ENDIF
;
;10/17/81 MODS TO SUPPORT CONTINUING A MSG IN MSG ENTRY
;
CECONT	MVI	A,1
	STA	MCONT	;SHOW CONTINUED
	JMP	ENTER	;THEN GO TO MSG ENTRY
;
;10/17/81 END
;
;
;HEX WITH SPACE
;
HEXB	CALL	HEX
	JMP	SPACE
;
;HEX PRINT ROUTINE
;
HEX	PUSH	PSW
	RAR
	RAR
	RAR
	RAR
	CALL	NIBBL
	pop	psw
nibbl	ani	0fh
	adi	90h
	daa
	aci	40h
	daa
	jmp	type
;
ceftab	db	'DIR '
	DW		CEDIR
	DB	'DIRN'
	DW		CEDIR
	DB	'ERA '
	DW		CEERA
	DB	'STAT'
	DW		CESTAT
	DB	'XCPM'
	DW		0
	DB	'NOTE'
	DW		CENOTE
	DB	'NAME'
	DW		GETFN
	DB	'DUMP'
	DW		CEDUMP
	DB	'ENTR'
	DW		CEENTR
02	DB	'PURG'
02	DW		PURGE
03	DB	'HOLD'
03	DW		HOLD
04	DB	'PRIN'
04	DW		CEPRINT
	DB	'SLOW'
	DW		CESLOW
	DB	'CONT'
	DW		CECONT
;
	DB	0	;END OF FUNCTION TABLE
;
	LINK	CBBSKILL

