;********************************************************
;* *
;* 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