;***************************************;
; ;
; S U R V E Y ;
; ;
;***************************************;
;By Michael Friese 9/22/79
;* Lists Kbytes used and remaining plus number of files
; on all logged disks (up to 8)
;* Prints Memory map and synopsis of all machine memory
;* Lists all active I/O Ports
;* Uses disk allocation block for all disk calculations
;
;VERSION LIST - Most recent version first.
;
;06/Jul/82 - Added Godbout DISK 1 equate and added SKIP equate
; Bill Bolton - Software Tools, Australia
;
;01/Jun/82 - Tidied up and fixed port display, added display
; of contents of low memory. David Bennett - Alfred
; Hospital, Australia
;
;29/Jun/80 - Added version number test and calculations for CP/M
; version 2 compatibility. This program should now work
; properly on all versions 1.4 and later. BRR
;
;28/Jun/80 - Added IMS400 equate (prevents Industrial Micro Systems
; controller from hanging up during port scan). BRR
;
;24/Jun/80 - Removed MACLIB statement, included required macros
; in source. Bruce R. Ratoff
;
;*******************************;
; SYSTEM MACROS ;
;*******************************;
;Increments 16 bit memory location X
INXI MACRO X
LOCAL JUST8
PUSH H
LXI H,X
INR M
JNZ JUST8
INX H
INR M
JUST8:
POP H
ENDM
;..............................................................
;
; SAVE MACRO SAVE SPECIFIED REGISTERS
;
; SAVE R1,R2,R3,R4
;
; R1-R4 MAY BE B,D,H OR PSW SAVED IN ORDER SPECIFIED
; IF REGS ARE OMITTED SAVE B,D AND H
;
SAVE MACRO R1,R2,R3,R4
IF NOT NUL R1&R2&R3&R4
IRP R,<<R1>,<R2>,<R3>,<R4>>
IF NUL R
EXITM
ENDIF
PUSH R
ENDM
ELSE
IRPC REG,BDH
PUSH REG
ENDM
ENDIF
ENDM
;
; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
; RESTORE MACRO RESTORE REGISTERS (INVERSE OF SAVE)
;
; RESTORE R1,R2,R3,R4
;
; R1-R4 MAY BE B,D,H OR PSW RESTORED IN ORDER SPECIFIED
; IF REGS OMITTED RESTORE H,D AND B
;
RESTORE MACRO R1,R2,R3,R4
IF NOT NUL R1&R2&R3&R4
IRP R,<<R1>,<R2>,<R3>,<R4>>
IF NUL R
EXITM
ENDIF
POP R
ENDM
ELSE
IRPC REG,HDB
POP REG
ENDM
ENDIF
ENDM
;
;..............................................................
;
; CHAROUT MACRO CONSOLE OUTPUT FROM A
;
; CHAROUT ADDR
;
CHAROUT MACRO ADDR
IF NOT NUL ADDR
LDA ADDR
ENDIF
MVI C,2 ;;CONOUT
MOV E,A ;;CHAR TO E
CALL 5 ;;CALL BDOS
ENDM
;
;
;.............................................................
;
; DECOUT MACRO CONVERT A POSITIVE INTEGER TO DECIMAL AND OUTPUT
; TO THE CONSOLE.
;
; DECOUT ADDR
;
; IF ADDR OMITTED, NUMBER ASSUMED TO BE IN HL, ELSE LOADED TO HL
; LEADING ZEROS SUPRESSED. MAXIMUM NUMBER 65,767
;
DECOUT MACRO ADDR
LOCAL ENDDEC,DX
JMP ENDDEC
@DECOUT:
SAVE ;;PUSH STACK
LXI B,-10 ;;RADIX FOR CONVERSION
LXI D,-1 ;;THIS BECOMES NO DIVIDED BY RADIX
DX:
DAD B ;;SUBTRACT 10
INX D
JC DX
LXI B,10
DAD B ;;ADD RADIX BACK IN ONCE
XCHG
MOV A,H
ORA L ;;TEST FOR ZERO
CNZ @DECOUT ;;RECURSIVE CALL
MOV A,E
ADI '0' ;;CONVERT FROM BCD TO HEX
MOV E,A ;;TO E FOR OUTPUT
CHAROUT ;;CONSOLE OUTPUT
RESTORE ;;POP STACK
RET
ENDDEC:
DECOUT MACRO ?ADDR
IF NOT NUL ?ADDR
LHLD ?ADDR
ENDIF
CALL @DECOUT ;;CALL THE SUBROUTINE
ENDM
DECOUT ADDR
ENDM
;
;
;..............................................................
;
; HEXOUT MACRO CONVERT BINARY NO AND OUTPUT TO CONSOLE
;
; HEXOUT ADDR
;
; NUMBER ASSUMED IN A IF NO ARGUMENT
;
HEXOUT MACRO ADDR
LOCAL OUTCHR,HEXEND
JMP HEXEND
HEXPRN:
SAVE PSW
RRC
RRC
RRC
RRC ;;SHIFT RIGHT 4
CALL OUTCHR
RESTORE PSW
OUTCHR:
ANI 0FH ;;MASK 4 BITS
ADI 90H ;;ADD OFFSET
DAA ;;DEC ADJUST
ACI 40H ;;ADD OFFSET
DAA ;;DEC ADJUST
MOV E,A ;;TO E FOR OUTPUT
MVI C,2 ;;CONOUT
JMP 5 ;;CALL BDOS
HEXEND:
HEXOUT MACRO ?ADDR
IF NOT NUL ?ADDR
LDA ?ADDR
ENDIF
CALL HEXPRN
ENDM
HEXOUT ADDR
ENDM
;
;
;*******************************;
; SYSTEM EQUATES ;
;*******************************;
TRUE EQU -1
FALSE EQU NOT TRUE
TARBEL EQU false ; Tarbell FDC dmb 31-may-82
IMS400 EQU FALSE ; Industrial Micro Systems FDC
GODBOUT EQU TRUE ; Godbout Disk 1 FDC
GODBAS EQU 0C0H ; Base of Godbout FDC
TARBAS EQU 0F8H ; Base of Tarbell
SKIP EQU TARBEL OR IMS400 OR GODBOUT ; Will be true
; if any skip needed
IF TARBEL
SKIPORT EQU TARBAS+4 ; Port # to skip if Tarbell FDC
ENDIF
IF IMS400
SKIPORT EQU 08FH ; Port # to skip if IMS FDC
ENDIF
IF GODBOUT
SKIPORT EQU GODBAS+1 ; Port # to skip if Disk 1 FDC
ENDIF
BDOS EQU 5 ; jump to BDOS
bios equ 0 ; jump to BIOS dmb 1-jun-82
CRLF EQU 0A0DH ; CR LF sequence
CRLFE EQU 8A0DH ; CR LF with EOL
EOL EQU 80H ; End of line
TAB EQU 'I'-40H ; Tab character
ESC EQU 1BH ; Escape character
TABS EQU 9 ; Tab columns
;***********************;
; MAIN PROGRAM ;
;***********************;
;
ORG 100H
;
START:
LXI H,0 ; Save stack pointer
DAD SP
SHLD OLDSP
LXI SP,FINIS+64
CALL TYPE ; Type initial CRLF
DB TAB,TAB,'*** System Survey (June 82) ***'
DW CRLF,CRLFE
;DISK SURVEY
LXI H,8 ; Init drive counter
MVI C,24 ; Get login vector
PUSH H
CALL BDOS
POP H
ROTBIT:
RAR ; RAR login bit to C
JNC NOTLOG ; Drive not logged
PUSH PSW ; Save login
PUSH H ; and counter
;Print drive letter
CALL TYPE
DB 'Drive'
DB ' '+EOL
MVI A,'A' ; Get ASCII bias
ADD H ; Add to drive #
MOV E,A ; Print drive letter
CALL TCHR
CALL TYPE ; and colon
DB ':',' '+EOL
POP H ; Restore drive #
PUSH H
;Print K already allocated
MOV E,H
MVI C,14 ; Log drive
CALL BDOS
MVI C,27 ; Index allocation vect
CALL BDOS
MOV L,A ; Put in decent regs
MOV H,B
PUSH H ; save for later
MVI C,12 ; get version #
CALL BDOS
MOV A,L ; zero if version 1
ORA A
JNZ V2X ; otherwise, use 2.x style params
LHLD BDOS+1 ; get vers 1 style params
MVI L,3CH
MOV A,M ; get block shift factor
STA BLKSHF
INX H
INX H
MOV L,M ; get max. block number
MVI H,0
SHLD MAXALL
MVI B,32 ; assume 32 bytes in block map
JMP GETALC ; continue
V2X:
MVI A,'?' ; Use wild user #
STA FCB ; in filename search
MVI C,31 ; Get 2.x parameter block
CALL BDOS
INX H
INX H
MOV A,M ; Get and save ablock shift factor
STA BLKSHF
INX H
INX H
INX H
MOV A,M ; Get maximum block number
INX H ; (double precision)
MOV H,M
MOV L,A
SHLD MAXALL
INX H
MVI B,3 ; map size is (MAXALL+1)/8
V2SH:
MOV A,H
ORA A ; do 16 bit right shift
RAR
MOV H,A
MOV A,L
RAR
MOV L,A
DCR B ; 3 times
JNZ V2SH
MOV B,L
LDA MAXALL ; allow for leftover bits if any
ANI 3
JZ GETALC
INR B
GETALC:
POP H
LXI D,0 ; Init group counter
NXBYTE:
MVI C,8 ; Bit counter for byte
MOV A,M ; Get map byte
NXBIT:
RAR ; Rotate to C
JNC NOBIT ; No group allocated
INX D ; Inc group counter
NOBIT:
DCR C ; Dec bit counter
JNZ NXBIT
INX H ; Index next byte
DCR B
JNZ NXBYTE
CALL SHF16
PUSH H
CALL BINDEC
CALL TYPE
DB 'K bytes in',' '+EOL
;Print number of files
LXI D,FCB ; Fake file cont block
MVI C,17 ; Search for 1st file
CALL BDOS
LXI H,0 ; File counter
LOOK:
CPI 255 ; Failure
JZ PFILE
ADD A ; File offset times 2
ADD A ; 4
ADD A ; 8
ADD A ; 16
ADD A ; 32
ADI 80H ; Make sure it's not a deleted file
MOV E,A
MVI D,0
LDAX D
CPI 0E5H
JZ LOOK1
INX H ; Bump file counter
LOOK1:
LXI D,FCB ; Restore FCB
MVI C,18 ; Look for addtl files
PUSH H ; Save file counter
CALL BDOS
POP H
JMP LOOK
PFILE:
CALL BINDEC ; Print # of files
CALL TYPE
DB ' files with',' '+EOL
;Print K remaining
LHLD MAXALL ; Get number of blocks
XCHG
INX D ; Inc for actual value
CALL SHF16
XCHG
POP H
MOV A,H ; Ones comp & move
CMA
MOV H,A
MOV A,L
CMA
MOV L,A
INX H ; Twos complement
DAD D ; and subtract
CALL BINDEC ; K remaining
CALL TYPE
DB 'K bytes remaining'
DW CRLFE
;Set up to print next drive
POP H ; Restore bit counter
POP PSW ; and bitmap byte
NOTLOG:
INR H ; Bump drive counter
DCR L ; Dec bit counter
JNZ ROTBIT
;MEMORY SURVEY
;Create header
MSURV:
CALL TYPE
DW CRLF
DB 'Memory map:'
DW CRLF
DB '0',TAB,'8',TAB,'16',TAB,'24',TAB,'32'
DB TAB,'40',TAB,'48',TAB,'56',TAB,'64'
DW CRLF
REPT 8
DB '|',TAB
ENDM
DB '|'
DW CRLF
db ' ' ; dmb 31-May-82
DB 'T'+EOL
LXI H,RAM
MVI M,LOW 1023 ; Init RAM counter
INX H
MVI M,HIGH 1023
MVI B,4 ; Clear ROM, EMP
CLREG:
INX H
MVI M,0
DCR B
JNZ CLREG
LXI H,1024 ; Init memory pointer
MVI C,63 ; K to be checked
;Start of analysis loop
BEGANA:
LXI D,1024 ; Byte counter
XRA A ; Clear flag bytes
STA RAMF
STA EMPF
ANALP:
MOV A,M ; Get test byte and
MOV B,A ; store for later
CMA
MOV M,A ; Put invertd tst byte
SUB M ; Check for good write
MOV M,B ; Restore orignl data
JNZ NOTMEM ; Wasn't good write
INXI RAM ; Bump memory counter
JMP NEXT ; To next byte
NOTMEM:
STA RAMF ; Not considered RAM
MVI A,0FFH ; Is it empty space?
SUB B
JNZ NOTEMP ; Inc ROM, set flag
LDA EMPF ; Any non empty space
ANA A ; before here?
JZ NEXT
JMP NOTEM ; To next byte
NOTEMP:
STA EMPF ; Set no empty flag
NOTEM:
INXI ROM
NEXT:
INX H ; Index next byte
DCX D ; Decrement K counter
XRA A
ORA D
ORA E
JNZ ANALP ; K counter not 0
PUSH B
PUSH H
LDA RAMF ; Is it RAM?
ANA A
JNZ NOTRAM ; No
dcr h ; drop H to make compares right
LDA BDOS+2 ; Is it under BDOS ?
CMP H
JC NOTTPA ; No
CALL TYPE ; Yes, it's TPA
DB 'T'+EOL
JMP NEXTK
NOTTPA:
lda bios+2 ; is it under bios ?
cmp h
jc nbdos
call type ; yes, it's BDOS
db 'C'+eol
jmp nextk
nbdos:
CALL TYPE ; Assume it's BIOS
DB 'B'+EOL
JMP NEXTK
;
NOTRAM:
LDA EMPF ; Is it empty?
ANA A
JZ NOMEM ; Yes, no memory
CALL TYPE ; No, must be ROM
DB 'R'+EOL
JMP NEXTK
NOMEM:
CALL TYPE
DB ' '+EOL
NEXTK:
POP H
POP B
DCR C ; Decrement K counter
JNZ BEGANA
CALL TYPE
DW CRLF
DB 'T=TPA',TAB,'C=CPM',TAB,'B=BIOS or unassigned'
DB TAB,'R=ROM or bad'
DW CRLFE
;
; contents of first page
call type
db 'BIOS at',' '+eol
hexout bios+2
hexout bios+1
call type
db tab,'iobyte',' '+eol
hexout bios+3
call type
db tab,'drive',' '+eol
hexout bios+4
call type
db tab,'BDOS at',' '+eol
hexout bdos+2
hexout bdos+1
call type
dw crlf,crlfe
;
;MEMORY SYNOPSIS
LHLD RAM
PUSH H ; Save RAM
CALL BINDEC ; Type RAM
CALL TYPE
DB ' Bytes RAM',TAB,TAB+EOL
LHLD ROM
PUSH H
CALL BINDEC ; Type ROM
CALL TYPE
DB ' Bytes ROM',TAB,TAB+EOL
LHLD BDOS+1
CALL BINDEC
CALL TYPE
DB ' Bytes in TPA'
DW CRLFE
POP D ; Get RAM
POP H ; Get RAM
DAD D ; Add 'em
PUSH H ; and save result
LXI D,0 ; Subtract from this
MOV A,H ; Complement 16 bits
CMA
MOV H,A
MOV A,L
CMA
MOV L,A ; 2s comp bias in D
DAD D ; Subtract
CALL BINDEC
CALL TYPE
DB ' Bytes Empty ',TAB+EOL
POP H ; Restore RAM+ROM
CALL BINDEC
CALL TYPE
DB ' Total Active Bytes'
DW CRLF,CRLF
;PORT SURVEY
DB 'Active I/O ports',':'+EOL
LXI H,1000H ; DELAY SO MESSAGE OUTPUT
PDLY:
DCX H ; DOESN'T GIVE A FALSE READING
MOV A,H ; ON CONSOLE STATUS PORT
ORA L
JNZ PDLY
LXI H,0 ; Init active port counter
mvi d,0 ; Init port counter
mvi e,0ffh ; init port group variable
PORTLP:
MOV A,D
IF SKIP ; Single port mask
CPI SKIPORT
JZ ISPORT ; Print mask port
ENDIF
mov b,a ; save port #
STA INPORT+1
INPORT:
IN 0 ; Modifiable code
; by trial and error, inactive port could return FF or echo port #
CPI 0FFH
JZ NEXTPT
cmp b
jz nextpt
ISPORT:
mov a,d ; got a live one, probably
ani 0f0h ; is port in same group as last ?
cmp e
jz nocrlf
call type ; no, start a new line
dw crlfe
mov a,d ; save for next time
ani 0f0h
mov e,a
nocrlf:
MOV A,D ; Get port #
PUSH D
PUSH H
HEXOUT
POP H
POP D
INX H ; count another one found
call type
db ' '+eol
NEXTPT:
INR D ; Bump port counter
JNZ PORTLP ; Not done
CALL TYPE ; Done
DW CRLFE
CALL BINDEC
CALL TYPE ; Type Active Ports
DB ' Ports active'
DW CRLFE
CCP:
LHLD OLDSP
SPHL
RET
;Binary to decimal conversion
BINDEC:
DECOUT ; From LIB
RET
;Types a string of text terminated with bit 7 high
TYPE:
XTHL ; Get string address
PUSH D
TYPELP:
MOV A,M ; Get type data
MOV D,A ; Save for later
ANI 7FH ; Mask ASCII
MOV E,A
PUSH H
PUSH D
CALL TCHR
POP D
POP H
INX H
MVI A,EOL ; End of line bit
ANA D
JP TYPELP ; Not done
POP D
XTHL ; Get return address
RET
;Types a single character on console
TCHR:
MVI C,2
JMP BDOS
;Checks sectors per block and multiplies or divides block size
;Enter with data in D. Result returned in H,L
;
SHF16:
LDA BLKSHF ; Get shift factor (gives block size)
CPI 3 ; Is it 1K (std)?
JNZ NOT3
MOV L,E ; Yes, use present #
ZH:
MVI H,0
RET
;
NOT3:
CPI 2 ; Is it minifloppy?
JNZ NOT2
MOV A,E ; Yes, divide by 2
RRC
ANI 7FH
MOV L,A
JMP ZH
NOT2:
SUI 3 ; Must be something
MOV B,A ; larger like double
XCHG ; sided or double dens
BITSHF:
DAD H ; 16 bit 2^(B-1)
DCR B
JNZ BITSHF
RET
;***********************;
; DATA STORAGE ;
;***********************;
FCB: DB 0,'???????????',0,0,0 ; File control block
DS 17 ; Extra FCB workspace
OLDSP: DS 2 ; Old stack pointer
RAM: DS 2 ; RAM counter
ROM: DS 2 ; ROM counter
RAMF: DS 1 ; RAM good flag
EMPF: DS 1 ; Empty so far flag
BLKSHF: DS 1 ; block shift factor
MAXALL: DS 2 ; maximum block number
FINIS EQU $ ; End of program
END