;********************************************************
;*							*
;*	Disassembly of T.COM from CBBS disks		*
;*							*
;********************************************************
;
;	Originally written by
;	Ward Christensen
;	and supplied with the CBBS package
;
;	Disassembly
;	By Bill Bolton
;	   "Software Tools" RCPM
;	   SYSOP
;
;VERSION LIST - most recent version first
;
;11/Aug/82 Fixed Control S "pause" to release on any char
;	   following, including another Control S. Bill Bolton
;
;02/Aug/82 Entering TYPE *.* would eventually yield a list of
;	   all the files on the disk, including tagged and SYS
;	   files. File type testing was rearranged to prevent
;	   this and COM and OBJ messages were deleted. Fixed bug
;	   due to error in disassembly concerning buffer size.
;	   Changed console input check to direct console I/O
;	   (BDOS 6) and added CP/M version trap. Added messages
;	   explaning how to look at some files that can't be 
;	   "type"d. Bill Bolton
;
;15/Jul/82 Diassembled and file type testing routines from
;	   MLIST50 merged in. Bill Bolton
;
;
BDOS	EQU	00005H		;CP/M BDOS entry point
FCB	EQU	0005CH		;CP/M file control block
SECTOR	EQU	80H		;Length of a CP/M sector
BUF$SIZE EQU	30H		;Size of buffer in pages
;
CNTRLC	EQU	3
TAB	EQU	9
ALF	EQU	0AH
ACR	EQU	0DH
CNTRLS	EQU	13H
CNTRLX	EQU	18H
CNTRLZ	EQU	1AH
;
CONOUT	EQU	2
DIRECT	EQU	6
STRING	EQU	9
VERSION EQU	12
OPEN	EQU	15
SEARCH$1ST EQU	17
SEARCH$NXT EQU	18
READ	EQU	20
SET$DMA	EQU	26
;
	ORG	100H
;
START:
	CALL	BEGIN
;
	DB	'TYPE Ver 5.3 - Multiple file lister',ACR,ALF,'$'
;
BEGIN:
	POP	D
	LXI	H,0
	DAD	SP
	SHLD	OLD$STACK	;Save entry stack
	LXI	SP,STACK$TOP	;Set up local stack
	MVI	C,STRING
	CALL	BDOS
	MVI	C,VERSION
	CALL	BDOS
	CPI	20H
	JNC	VERSION$OK
	CALL	PRN$EXIT
;
	DB	'Sorry, you need CP/M Version 2.0 or later to run TYP'
	DB	ACR,ALF,ACR,ALF,'$'
;	
VERSION$OK:
	LDA	FCB+1
	CPI	' '		;File name specified?
	JNZ	HEADER		;Yes
	CALL	PRN$EXIT	;No, show usage
;
	DB	'TYPE command usage:',ACR,ALF,ACR,ALF
	DB	'	TYPE name',ACR,ALF
	DB	'	TYPE name nn',ACR,ALF
	DB	'	TYPE name #',ACR,ALF
	DB	'	TYPE name label',ACR,ALF,ACR,ALF
	DB	'Where:',ACR,ALF,ACR,ALF
	DB	'	name	Any file name.  * and ? allowed',ACR,ALF
	DB	'	nn	A starting line # (1 = first)',ACR,ALF
	DB	'	#	Means to count # of lines',ACR,ALF
	DB	'	label	Skip to label before printing',ACR,ALF
	DB	'		Must match exactly and completely',ACR,ALF
	DB	'		To match leading chars, end the string with *:'
	DB	ACR,ALF
	DB	'			TYPE b:foo.asm tr*',ACR,ALF,'$'
;
HEADER:
	CALL	PRN$MSG
;
	DB	ACR,ALF
	DB	'CTL-S pauses, CTL-X skips to next file, CTL-C aborts'
	DB	ACR,ALF,ACR,ALF,0
;
	LDA	FCB+17
	CPI	' '	;More command line?
	JZ	NEXT	;No
	CPI	'0'	;Yes,line number?
	JC	A02AE	;No
	CPI	':'
	JC	A02BD	;Yes
A02AE:
	LXI	H,FCB+17	;Point to secondary FCB
	LXI	D,D0707		;Internal buffer
	LXI	B,11		;Length to move
	CALL	MOVER		;Do it
	JMP	NEXT
;
A02BD:
	LXI	D,FCB+17
	LXI	H,0
A02C3:
	LDAX	D
	INX	D
	CPI	' '
	JZ	A0302
	CPI	'0'
	JC	A02E5
	CPI	':'
	JNC	A02E5
	SUI	'0'
	MOV	B,H
	MOV	C,L
	DAD	H
	DAD	H
	DAD	B
	DAD	H
	ADD	L
	MOV	L,A
	JNC	A02C3
	INR	H
	JMP	A02C3
;
A02E5:
	CALL	PRN$EXIT
;
	DB	'++INVALID STARTING LINE #$'
;
A0302:
	MOV	A,H
	ORA	L
	JZ	A0308
	DCX	H
A0308:
	SHLD	D0705
NEXT:
	LXI	SP,STACK$TOP	;Reset stack
	CALL	A062D
	JC	EXIT
	CALL	A031C
;
	DB	'     '
;
A031C:
	POP	H
	LXI	B,5		;Length to move
	LXI	D,T043D
	CALL	MOVER
	CALL	A032F
;
	DB	'      '
;
A032F:
	POP	H
	LXI	B,6		;Length to move
	LXI	D,T044B
	CALL	MOVER
	LXI	H,0
	SHLD	D0700
	MVI	C,OPEN		;Open file
	LXI	D,FCB
	CALL	BDOS
	INR	A		;Good open?
	JZ	EXIT		;No
;
;Check for file protected by CP/M 2.x f2' attribute
;
CKFIL:	LDA	FCB+10		;POINT TO SYS FILE ATTR
	ANI	80H		;IS IT SYS?
	JNZ	NEXT		;SYS file, can't print it
;
;Check for .COM file, which can't be printed
;
	LDA	FCB+11
	CPI	'M'		;WAS LAST CHAR AN 'M'?
	JNZ	OBJCHK		;IF NOT, CHK FOR '.OBJ' TYPE
	LDA	FCB+10
	ANI	7FH		;STRIP CP/M 2.x ATTR
	CPI	'O'		;AN 'O'?
	JNZ	OBJCHK		;IF NOT IT'S OK TO PRINT
	LDA	FCB+9
	ANI	7FH		;STRIP CP/M 2.x ATTR
	CPI	'C'		;'C' AS IN '.COM'?
	JNZ	OBJCHK		;IF NOT, IT'S OK TO PRINT
	JMP	NEXT		;MORE TO PRINT?
;
;Check for .OBJ file, which can't be printed
;
OBJCHK:
	CPI	'J'		;WAS LAST CHAR AN 'J' ?
	JNZ	SHOW$NAME	;IF NOT, OK TO LIST
	LDA	FCB+10		;MIGHT BE '.OBJ', CHK NEXT CHR
	ANI	7FH		;STRIP CP/M 2.x ATTR
	CPI	'B'		;IS IT A 'B'?
	JNZ	SHOW$NAME	;IF NOT, LIST
	LDA	FCB+9		;WAS, CHK FIRST CHAR
	ANI	7FH		;STRIP CP/M 2.x ATTR
	CPI	'O'		;'O' AS IN '.OBJ'?
	JNZ	SHOW$NAME	;IF NOT, PRINT THE FILE, IF SO
	JMP	NEXT		;MORE TO PRINT?
;
SHOW$NAME:
	LXI	H,FCB+1		;Point to primary file name
	LXI	D,PRIMARY
	LXI	B,8		;Length
	CALL	MOVER
	LXI	H,FCB+9		;Point to secondary file name
	LXI	D,SECNDRY
	LXI	B,3		;Length
	CALL	MOVER
	CALL	PRN$MSG
;
	DB	ACR,ALF,ACR,ALF
	DB	'===> LISTING FILE: '
PRIMARY:
	DB	'XXXXXXXX.'
SECNDRY:
	DB	'XXX',ACR,ALF,ACR,ALF
	DB	0
;
	LDA	FCB+2		;POINT TO TAG FILE ATTR
	ANI	80H		;IS IT TAGGED?
	JZ	SQCHK		;NO, CHECK IF SQUEEZED
	CALL	PRN$MSG		;PRINT:
;
	DB	'++FILE NOT FOR DISTRIBUTION, SORRY++',ACR,ALF,0
;
	LDA	FCB+11
	CPI	'L'		;WAS LAST CHAR AN 'L' ?
	JNZ	HLPCHK		;IF NOT, OK TO LIST
	LDA	FCB+10		;MIGHT BE '.ALL', CHK NEXT CHR
	ANI	7FH		;STRIP CP/M 2.x ATTR
	CPI	'L'		;IS IT A 'L'?
	JNZ	HLPCHK		;IF NOT, LIST
	LDA	FCB+9		;WAS, CHK FIRST CHAR
	ANI	7FH		;STRIP CP/M 2.x ATTR
	CPI	'A'		;'A' AS IN '.ALL'?
	JNZ	HLPCHK		;NO, NEXT CHECK
	CALL	PRN$MSG
;
	DB	ACR,ALF
	DB	'++Use DISPLAY to look at this Catalogue++'
	DB	ACR,ALF,0
	JMP	NEXT		;MORE TO PRINT?
;
HLPCHK:
	LDA	FCB+11		;POINT TO LAST CHAR OF FTYPE
	CPI	'P'
	JNZ	NXTCHK		;IF NOT, OK TO LIST
	LDA	FCB+10		;MIGHT BE '.HLP', CHK NEXT CHR
	ANI	7FH		;STRIP CP/M 2.x ATTR
	CPI	'L'		;IS IT A 'L'?
	JNZ	NXTCHK		;IF NOT, LIST
	LDA	FCB+9		;WAS, CHK FIRST CHAR
	ANI	7FH		;STRIP CP/M 2.x ATTR
	CPI	'H'		;'H' AS IN '.HLP'?
	JNZ	NXTCHK		;NO, NEXT CHECK
	CALL	PRN$MSG
;
	DB	ACR,ALF
	DB	'++Use HELP to look this "HLP" file++'
	DB	ACR,ALF,0
	JMP	NEXT		;MORE TO PRINT?
;
NXTCHK:
	JMP	NEXT
;
;Check for possible 'squeezed' file, which will not print
;
SQCHK:
	LDA	FCB+10		;GET SECOND CHAR OF FILETYPE
	ANI	7FH		;STRIP ATTRIBUTE
	CPI	'Q'		;THIS MAY BE SQUEEZED FILE
	JNZ	A038A		;NOT SQUEEZED
	CALL	PRN$MSG		;PRINT:
;
	DB	'NOTE: If this file doesn''t '
	DB	'print correctly, try TYPE in XYAM.',ACR,ALF
	DB	'Most files with "Q" as 2nd char. '
	DB	'of filetype are squeezed.',ACR,ALF,ACR,ALF,0
;
A038A:
	LXI	H,BUF$END
	MVI	B,1
A038F:
	PUSH	B
	PUSH	D
	PUSH	H
	LXI	H,T06FE
	CALL	A057C
	POP	H
	POP	D
	POP	B
	CPI	CNTRLZ		;End of file?
	JZ	A03ED
	ANI	07FH		;Strip of MSB (WordStar?)
	CPI	ACR
	JZ	A03C0
	CPI	TAB
	JNZ	A03BA
TABER:
	MVI	M,' '
	INX	H
	INR	B
	MOV	A,B
	DCR	A
	ANI	007H		;Reached next TAB stop?
	JNZ	TABER		;No
	JMP	A038F		;Yes
;
A03BA:
	MOV	M,A
	INX	H
	INR	B
	JMP	A038F
;
A03C0:
	MVI	M,' '
	INX	H
	MOV	M,A
	PUSH	B
	PUSH	D
	PUSH	H
	LXI	H,T06FE
	CALL	A057C
	POP	H
	POP	D
	POP	B
	CALL	CONSOLE$CHK
	JC	NEXT
	LDA	D0707
	CPI	'#'
	JZ	A038A
	LHLD	D0705
	MOV	A,H
	ORA	L
	JZ	A045E
	DCX	H
	SHLD	D0705
	JMP	A038A
;
A03ED:
	LHLD	D0705
	MOV	A,H
	ORA	L
	JZ	A0415
	CALL	PRN$EXIT
;
	DB	'++STARTING LINE # TOO HIGH++$'
;
A0415:
	LDA	D0707
	CPI	' '
	JZ	NEXT
	CPI	'#'
	JZ	A043A
	CALL	PRN$EXIT
;
	DB	'++STRING NOT FOUND++$'
;
A043A:
	CALL	PRN$MSG
;
T043D:
	DB	'     '
T0442:
	DB	'  LINES, '
T044B:
	DB	'      '
T0451:
	DB	'  BYTES',ACR,ALF,0
;
	JMP	NEXT
;
A045E:
	LDA	D0707
	CPI	' '
	JZ	A048F
	LXI	H,D0707
	LXI	D,BUF$END
A046C:
	LDAX	D
	CPI	' '
	JZ	A0489
	CPI	':'
	JZ	A0489
	CMP	M
	JNZ	A0480
	INX	D
	INX	H
	JMP	A046C
;
A0480:
	MOV	A,M
	CPI	'?'
	JZ	A048F
	JMP	A038A
;
A0489:
	MOV	A,M
	CPI	' '
	JNZ	A038A
A048F:
	MVI	A,' '
	STA	D0707
	MVI	C,0
	LXI	H,BUF$END
A0499:
	MOV	A,M
	CPI	' '
	JNZ	A04A9
	CPI	ACR
	JZ	A04A9
	INX	H
	INR	C
	JMP	A0499
;
A04A9:
	LXI	H,BUF$END
	MVI	B,1
A04AE:
	PUSH	B
	PUSH	H
A04B0:
	MOV	A,M
	INX	H
	INR	B
	CPI	ACR
	JZ	A04E6
	CPI	' '
	JNZ	A04B0
	MOV	A,B
	POP	H
	POP	B
	CPI	'P'
	JC	A04EA
	JZ	A04EA
	CALL	PRN$MSG
	DCR	C
	LDAX	B
	NOP
	PUSH	B
A04CF:
	XRA	A
	ORA	C
	JZ	A04E7
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,DIRECT	;Console out
	LXI	D,' '
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	DCR	C
	JMP	A04CF
;
A04E6:
	POP	H
A04E7:
	POP	B
	MVI	B,1
A04EA:
	MOV	E,M
	INR	B
	MOV	A,M
	CPI	' '
	JNZ	A04F8
	MOV	A,B
	CPI	'P'
	JZ	A0503
A04F8:
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,DIRECT	;Console out
	CALL	BDOS
	POP	H
	POP	D
	POP	B
A0503:
	CALL	CONSOLE$CHK
	JC	NEXT
	MOV	A,M
	INX	H
	CPI	ACR
	JZ	SEND$LF
	CPI	' '
	JNZ	A04EA
	JMP	A04AE
;
DIR$CON:
	PUSH	B
	PUSH	D
	PUSH	H
	LXI	D,0FFH
	MVI	C,DIRECT	;Direct Console input
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	ORA	A
	RET
;
CONSOLE$CHK:
	CALL	DIR$CON
	RZ
CONTROL$CHK:
	CPI	CNTRLC		;Abort ?
	JZ	ABORT		;Yes
	CPI	CNTRLX		;Skip to next file?
	JZ	SKIP		;Yes
	CPI	CNTRLS		;Pause for a while?
	JNZ	NO$ACTION	;No
PAUSE$LOOP:
	CALL	DIR$CON		;Another key pressed
	JZ	PAUSE$LOOP	;No
	CPI	CNTRLS		;Yes, go again?
	JZ	NO$ACTION	;Yes
	JMP	CONTROL$CHK	;No, check it
;
NO$ACTION:
	ORA	A		;Reset flags
	RET
;
SKIP:
	CALL	PRN$MSG
;
	DB	ACR,ALF,ACR,ALF,'++SKIPPING TO NEXT FILE++',0
;
	STC
	RET
;
SEND$LF:
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,DIRECT	;Console out
	LXI	D,ALF
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	JMP	A038A
;
PRN$MSG:
	XTHL
MSG$LOOP:
	MOV	E,M
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,DIRECT		;Console out
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	INX	H
	MOV	A,M
	ORA	A
	JNZ	MSG$LOOP
	XTHL
	RET
;
MOVER:
	MOV	A,M		;Get a byte from source
	STAX	D		;Put into destination
	INX	H		;Adjust pointers
	INX	D
	DCX	B		;Adjust counter
	MOV	A,B
	ORA	C		;Done?
	JNZ	MOVER		;No
	RET
;
A057C:
	MOV	E,M
	INX	H
	MOV	D,M
	INX	H
	MOV	C,M
	INX	H
	MOV	B,M
	MOV	A,B
	ORA	C
	JNZ	A05D1
	INX	H
	MOV	A,M
	ADD	A
	MOV	B,A
	INX	H
	PUSH	H
	MOV	A,M
	INX	H
	MOV	H,M
	MOV	L,A
A0592:
	CALL	CONSOLE$CHK
	JC	NEXT
	MVI	A,CNTRLZ
	STAX	D
	PUSH	D
	PUSH	H
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,SET$DMA	;Set DMA address
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	POP	D
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,READ		;Read sequential
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	ORA	A
	POP	H
	JNZ	A05C6
	MOV	A,L
	ADI	080H
	MOV	L,A
	MOV	A,H
	ACI	0
	MOV	H,A
	XCHG
	DCR	B
	JNZ	A0592
A05C6:
	POP	H
	DCX	H
	MOV	A,M
	DCX	H
	MOV	M,A
	DCX	H
	DCX	H
	DCX	H
	JMP	A057C
;
A05D1:
	INX	H
	MOV	A,M
	XCHG
	ADD	H
	MOV	H,A
	MOV	A,L
	SUB	C
	MOV	L,A
	MOV	A,H
	SBB	B
	MOV	H,A
	MOV	A,M
	XCHG
	CALL	A05EF
	CPI	ALF
	CZ	A05FA
	CPI	CNTRLZ
	RZ
	DCX	B
	DCX	H
	MOV	M,B
	DCX	H
	MOV	M,C
	RET
;
A05EF:
	PUSH	H
	LXI	H,T0451
A05F3:
	PUSH	PSW
	CALL	A0601
	POP	PSW
	POP	H
	RET
;
A05FA:
	PUSH	H
	LXI	H,T0442
	JMP	A05F3
;
A0601:
	MOV	A,M
	ORI	'0'
	INR	A
	MOV	M,A
	CPI	':'
	RNZ
	MVI	M,'0'
	DCX	H
	JMP	A0601
;
; >> NO EXECUTION PATH TO HERE <<
	PUSH	PSW
	RAR
	RAR
	RAR
	RAR
	CALL	A0618
	POP	PSW
A0618:
	ANI	00FH
	ADI	090H
	DAA
	ACI	040H
	DAA
	MOV	E,A
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,DIRECT
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	RET
;
A062D:
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,SET$DMA		;Set DMA address
	LXI	D,00080H
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	XRA	A
	STA	FCB+12
	STA	FCB+32
	LDA	D06DA
	ORA	A
	JNZ	A067D
	MVI	A,1
	STA	D06DA
	LXI	H,FCB
	LXI	D,T06DB
	LXI	B,12
	CALL	MOVER
	LDA	FCB
	STA	CDISK
	LXI	H,T06DB
	LXI	D,FCB
	LXI	B,12
	CALL	MOVER
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,SEARCH$1st	;Search for first
	LXI	D,FCB
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	JMP	A06B1
;
A067D:
	LXI	H,CDISK
	LXI	D,FCB
	LXI	B,12
	CALL	MOVER
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,SEARCH$1st		;Search for first
	LXI	D,FCB
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	LXI	H,T06DB
	LXI	D,FCB
	LXI	B,12
	CALL	MOVER
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,SEARCH$NXT	;Search for next
	LXI	D,FCB
	CALL	BDOS
	POP	H
	POP	D
	POP	B
A06B1:
	INR	A
	STC
	RZ
	DCR	A
	ANI	3
	ADD	A
	ADD	A
	ADD	A
	ADD	A
	ADD	A
	ADI	081H
	MOV	L,A
	MVI	H,0
	PUSH	H
	LXI	D,T06E8
	LXI	B,11
	CALL	MOVER
	POP	H
	LXI	D,FCB+1
	LXI	B,11
	CALL	MOVER
	XRA	A
	STA	FCB+12
	RET
;
D06DA:
	DB	0
T06DB:
	DB	0,0,0,0,0,0,0,0,0,0
	DB	0,0
CDISK:
	DB	0
T06E8:
	DB	0,0,0,0,0,0,0,0,0,0
	DB	0
;
ABORT:
	CALL	PRN$EXIT
;
	DB	ACR,ALF,ACR,ALF,'++ABORTED++',ACR,ALF,'$'
;
PRN$EXIT:
	POP	D
	MVI	C,STRING	;Print string
	CALL	BDOS
EXIT:
	LHLD	OLD$STACK
	SPHL
	RET
;
T06FE:
	DW	BUFFER
D0700:
	DB	0,0
	DB	BUF$SIZE
	DW	FCB
D0705:
	DW	0
D0707:
	DB	020H
;
	DB	0,0,0,0,0,0,0,0,0,0
	DB	0,0,0,0,0,0,0,0,0,0
	DB	0,0,0,0,0,0,0,0,0,0
	DB	0,0,0,0,0,0,0,0,0,0
	DB	0,0,0,0,0,0,0,0,0,0
	DB	0,0,0,0,0,0,0,0,0,0
	DB	0,0,0,0,0,0,0,0,0,0
	DB	0,0,0,0,0,0,0,0,0,0
	DB	0,0,0,0,0,0,0,0,0,0
	DB	0,0,0,0,0,0,0,0,0,0
	DB	0,0,0,0,0,0,0,0,0,0
STACK$TOP:
;
OLD$STACK:
	DW	0
;
BUFFER	EQU	$
BUF$END	EQU	$ + ((2 * BUF$SIZE) * SECTOR) ;Length of buffer
;
	END

