;
;	WHODERE.ASM by R.H.JOHNSON
;	Modifications by BILL WOOD (New name WHODERE1.ASM)
;
;	What you say in secret,
;		shall be shouted from the house tops.
;
; An SAU to display sneaky Bios reads and writes.
;
;	   A DEBUG PROGRAM FOR DISK READS AND WRITES
; This program will list all disk reads and writes to the
; CRT: (if CRT is TRUE) or to the LST: (if CRT is FALSE).
;
; N O T E :  This program runs in HI memory.
;	     CP/M must be moved below HI memory to allow
;	     room for this program. Set LOAD above CP/M.
;
;	     As this program must use direct BIOS call
;	     for CONOUT, the program may not work with
;	     future releases of CP/M . The BDOS call "6"
;	     for direct BIOS calls will not work with
;	     this program as we would have two BDOS
;	     call at the same time.	      B Wood.
;
;MODIFICATIONS:
;			------------
;03/30/82
;	Added routine to locate the address of BIOS.
;	Added conditional for output to CRT: or LST: .
;	Removed LDIR macro and added subroutine LDIR
;	to move memory. Program will now assemble with
;	ASM.COM .
;	Made other minor changes to program.
;
;		Bill Wood , Mississauga, Ontario, Canada.
;			------------
;
;04/02/82
;	Added on/off toggle for print out with CTRL ^A .
;	Check so program will not load a second time.
;	       Bill Wood
;			------------
;
;
FALSE	EQU	0
TRUE	EQU	NOT FALSE
;
LOAD	EQU	62	;FREE MEMORY SPACE ABOVE CP/M (IN K)
;
NEWBIOS EQU	(LOAD*1024)+1
;
CRT	EQU	TRUE	;OUTPUT TO CRT: IF TRUE (LST: IF FALSE)
;
BASE	EQU	0	;BASE OF CP/M
BDOS	EQU	BASE+5	;BDOS CALL
STRING	EQU	09H	;BDOS PRINT STRING
CR	EQU	0DH
LF	EQU	0AH
;
;
	ORG	100H
;
;DO NOT ALLOW PROGRAM TO BY LOADED A SECOND TIME (SYSTEM WILL CRASH)
START:	LHLD	BASE+1	;GET BIOS ADDRESS IN HL
	LXI	B,07H	;GET TO CONIN JMP ADDRESS
	DAD	B	;ADD BC TO HL
	MOV	E,M
	INX	H
	MOV	D,M	;ADDRESS NOW IN DE
	LXI	H,NEWIN ;GET ADDRESS
	MOV	A,H
	CMP	D
	JNZ	START1	;IF NOT SAME MUST BE 1ST. LOAD
	MOV	A,L
	CMP	E
	JNZ	START1	;IF NOT SAME MUST BE 1ST. LOAD
	LXI	D,LOADED
	MVI	C,STRING ;TELL THIS IS SECOND LOAD
	CALL	BDOS
	JMP	BASE	;GET BACK TO CM/M
;
LOADED: DB	CR,LF,'DUMMY !	  WHODERE1 IS LOADED'
	DB	CR,LF,'USE CTRL ^A TO TURN PROGRAM ON',CR,LF,'$'
;
;
;OK LOAD PROGRAM
;SET UP LOGOUT FOR CRT: OR LST:
START1: LHLD	BASE+1	 ;GET BIOS ADDRESS IN HL
	LXI	B,18H	 ;OFFSET TO SETDSK
	DAD	B	 ;ADD BC TO HL
	SHLD	WASBIOS  ;STORE IT
;
	LHLD	BASE+1	 ;GET BIOS ADDRESS IN HL
 ;
	IF	CRT
	LXI	B,9H	 ;CONOUT (CRT:)
	ENDIF
;
	IF	NOT CRT
	LXI	B,12	 ;LIST	(LST:)
	ENDIF
;
	DAD	B	 ;ADD BC TO HL
	SHLD	OVLAY1+1 ;OVERLAY BIOS CALL+1  CRT: OR LST:
;
;SET UP CONOUT FOR CRTMSG
	LHLD	BASE+1	 ;GET BIOS ADDRESS IN HL
	LXI	B,9H	 ;CONOUT
	DAD	B	 ;ADD TO HL
	SHLD	OVLAY2+1 ;OVERLAY BIOS CALL+1 CRT:
;
;
;SET UP TO TEST BIOS CONIN FOR CTRL ^A
	LHLD	BASE+1
	LXI	B,07H	 ;OFFSET TO CONIN
	DAD	B	 ;ADD BC TO HL
	MOV	E,M
	INX	H
	MOV	D,M
	XCHG
	SHLD	OVLAY3+1 ;OVERLAY CONIN CALL+1
;
;
;	COPY PROGRAM TO HIGH CORE
	LXI	H,PROGRAM
	LXI	D,NEWBIOS
	LXI	B,PROEND-PROGRAM
	CALL	LDIR
;
;	COPY OLD BIOS JUMPS TO TABLE
	LHLD	WASBIOS
	LXI	D,OLDDSK
	LXI	B,18
	CALL	LDIR
;
;	COPY IN NEWBIOS TABLE
	LHLD	WASBIOS
	XCHG
	LXI	H,SELDSK
	LXI	B,18
	CALL	LDIR
;
	LXI	H,NEWIN
	XCHG		 ;OVERLAY BIOS CONIN JMP
	LHLD	BASE+1
	LXI	B,07H	 ;OFFSET TO CONIN
	DAD	B	 ;ADD BC TO HL
	MOV	M,E
	INX	H
	MOV	M,D
;
	LXI	D,SIGNIN
	MVI	C,STRING ;PRINT STRING
	CALL	BDOS
;	DONE
	JMP	BASE
;
;
WASBIOS:DS	2
;
SIGNIN: DB	' WHODERE1.ASM '
	DB	' VERSION 2.1 '
	DB	' 3/03/82  R.H.JOHNSON',CR,LF
	DB	' REV(1) BY BILL WOOD 03/30/82',CR,LF,LF
	IF	CRT
	DB	' ALL DISK READS AND WRITES WILL DISPLAY ON CRT:',CR,LF,LF
	ENDIF
	IF	NOT CRT
	DB	' ALL DISK READS AND WRITES WILL DISPLAY ON LST:',CR,LF,LF
	ENDIF
	DB	'   N O T E :  USE CTRL ^A TO TOGGLE WHODERE ON & OFF',CR,LF
	DB	'		   WHODERE IS NOW OFF',CR,LF,LF,'$'
;
;
;	MOVE MEMORY
;	HL=GET	  DE=PUT     BC=COUNT
;
LDIR:	MOV	A,B
	ORA	C
	RZ		;RETURN IF COUNT IS 0
	MOV	A,M	;GET IT
	INX	H
	XCHG
	MOV	M,A	;PUT IT
	INX	H
	XCHG
	DCX	B	;COUNT
	JMP	LDIR
;
;
;
;	BIOS OVERLAY TABLE
;
SELDSK: JMP	NEWDSK
SETTRK: JMP	NEWTRK
SETSEC: JMP	NEWSEC
SETDMA: JMP	NEWDMA
SETRED: JMP	NEWRED
SETWRT: JMP	NEWWRT
;
;
;	START OF RELOCATED CODE
;
PROGRAM:EQU	$
OFFSET: EQU	NEWBIOS-PROGRAM
;
NEWIN:	EQU	$+OFFSET
OVLAY3: CALL	$-$	;BIOS CONIN (ADDRESS OVERLAY)
	PUSH	PSW	;TEST ALL CONIN'S FOR CTRL A
	ANI	7FH	;STRIP IT
	CPI	01H	;CTRL A
	JZ	TOGFLA	;YES TOGGLE PRINT FLAG
	POP	PSW
	RET
;
TOGFLA: EQU	$+OFFSET ;PRINT FLAG
	PUSH	H
	PUSH	D	;PSW IS PUSHED
	PUSH	B
	LXI	H,FLAG
	MOV	A,M	;GET FLAG
	CMA		;FLIP IT (TOGGLE)
	MOV	M,A	;PUT IT BACK
	CPI	0
	JZ	TOG1	;IT'S OFF SO SAY IT
	LXI	H,FLGON ;IT'S ON SO SAY IT
	JMP	TOG2
TOG1:	EQU	$+OFFSET
	LXI	H,FLGOFF
TOG2:	EQU	$+OFFSET
	CALL	CRTMSG	;PRINT MESSAGE (ON OR OFF)
	POP	B	;MUST USE BIOS AS WE HAVE A BDOS CONIN CALL
	POP	D	;ON THE GO. CAN'T HAVE TWO BDOS CALLS AT THE
	POP	H	;SAME TIME.
	POP	PSW
	MVI	A,CR	;SEND BACK A CR
	RET
;
FLAG:	EQU	$+OFFSET
	DB	0	;START WITH PRINT FLAG NOT SET
;
FLGON:	EQU	$+OFFSET
	DB	'^A WHODERE ON',CR,LF,0
FLGOFF: EQU	$+OFFSET
	DB	'^A WHODERE OFF',CR,LF,0
;
;
NEWDSK: EQU	$+OFFSET	;CONVERT DISK # TO LETTER
	PUSH	PSW		;PUT IN TABLE,
	MOV	A,C		;AND DOIT
	STA	TDISK
	POP	PSW
	JMP	OLDDSK
;
NEWTRK: EQU	$+OFFSET	;SEEK TO TRACK
	PUSH	PSW		;PUT IN TABLE,
	MOV	A,C		;AND DOIT
	STA	TTRACK
	POP	PSW
	JMP	OLDTRK
NEWSEC: EQU	$+OFFSET	;SET SECTOR NUMBER
	PUSH	PSW		;PUT IN TABLE,
	MOV	A,C		;AND DOIT
	STA	TSECT
	POP	PSW
	JMP	OLDSEC
NEWDMA: EQU	$+OFFSET	;SET START ADDRESS FOR I/O
	PUSH	PSW		;PUT IN TABLE,
	MOV	A,B		;AND DOIT
	STA	TDMA
	MOV	A,C
	STA	TDMA+1	
	POP	PSW
	JMP	OLDDMA
NEWRED: EQU	$+OFFSET	;READ SELECTED SECTOR
	PUSH	PSW		;PUT IN TABLE, DISPLAY
	MVI	A,'R'		;AND DOIT
	STA	OPCD
	CALL	CNVERT
	POP	PSW
	JMP	OLDRED
NEWWRT: EQU	$+OFFSET	;WRITE SELECTED SECTOR
	PUSH	PSW		;PUT IN TABLE, DISPLAY
	MVI	A,'W'		;AND DOIT
	STA	OPCD
	CALL	CNVERT
	POP	PSW
	JMP	OLDWRT
;
; CONVERTS STRING POINTED TO BY HL AND PUTS
; RESULT IN MEMORY POINTED TO BY DE
CNVERT: EQU	$+OFFSET
	PUSH	H
	LXI	H,FLAG	;TEST PRINT FLAG
	MOV	A,M
	CPI	0
	JNZ	CNVER1	;FLAG IS SET SO PRINT IT
	POP	H
	RET		;FLAG NOT SET SO NO PRINT OUT
CNVER1: EQU	$+OFFSET
	PUSH	D
	PUSH	B
	LXI	H,TDISK
	LXI	D,DISK
	CALL	CVERT
;
	LXI	H,TTRACK
	LXI	D,TRACK
	CALL	CVERT
;
	LXI	H,TSECT
	LXI	D,SECT
	CALL	CVERT
;
	LXI	H,TDMA
	LXI	D,DMA
	CALL	CVERT
;
	LXI	H,TDMA+1
	LXI	D,DMA+2
	CALL	CVERT
;
	LXI	H,TABSTG
	CALL	MSG	
	POP	B
	POP	D
	POP	H
	RET
;
;
CVERT:	EQU	$+OFFSET
	MOV	A,M
	ANI	0F0H
	RRC
	RRC
	RRC
	RRC	;CONVERT THE HIGH NIBBLE FIRST
	CALL	ASCII
	STAX	D	
	INX	D
	MOV	A,M	;STORE CHAR IN PRINT LINE
	ANI	0FH
	CALL	ASCII
	STAX	D
	RET		;CONVERT LOW NIBBLE
;
;
;CONVERT A TO ASCII
;
ASCII:	EQU	$+OFFSET
	ADI	30H
	CPI	'9'+1	;FE 3A OPCODE
	RM		
	ADI	7
	RET		;A NOW IN ASCIIFORM
;
;PMSG STRING POINTED TO BY HL TO LOGOUT
;MSB OF 1 IN LAST CHARACTER SENDS CR,LF.
;ZERO WILL ALSO END STRING WITH NO CR,LF...
;
;
MSG:	EQU	$+OFFSET
	MOV	C,M	;C=CHAR TO SEND TO CONSOLE
	CALL	LOGOUT
	MOV	A,M
	ANI	80H
	JNZ	LFCR	;LAST ONE IF MSB=1
	INX	H
	MOV	A,M
	ORA	A	;TEST CHAR FOR 0
	RZ
	JMP	MSG
;
;SEND CR,LF TO CONSOLE
;
LFCR:	EQU	$+OFFSET
	MVI	C,CR
	CALL	LOGOUT
	MVI	C,LF
	CALL	LOGOUT
	RET
;
LOGOUT: EQU	$+OFFSET
	PUSH	H
	MOV	A,C
	ANI	7FH	;STRIP HIGH BIT
	MOV	C,A	;PUT IT BACK IN C FOR BIOS
OVLAY1: CALL	$-$	;CALL BIOS (ADDRESS OVERLAYED)
	POP	H
	RET
;
;PRINT MESSAGE TO CRT VIA BIOS
CRTMSG: EQU	$+OFFSET
	MOV	C,M	;C=CHAR TO SEND TO CONSOLE
	PUSH	H
OVLAY2: CALL	$-$	;BIOS CONOUT
	POP	H
	INX	H
	MOV	A,M
	ORA	A	;TEST CHAR FOR 0
	RZ
	JMP	CRTMSG
;
;	OLD BIOS STORAGE
OLDDSK: EQU	$+OFFSET
	DB 0,0,0
OLDTRK: EQU	$+OFFSET
	DB 0,0,0
OLDSEC: EQU	$+OFFSET
	DB 0,0,0
OLDDMA: EQU	$+OFFSET
	DB 0,0,0
OLDRED: EQU	$+OFFSET
	DB 0,0,0
OLDWRT: EQU	$+OFFSET
	DB 0,0,0
;
;PRINT TABLE STORAGE
TABSTG: EQU	$+OFFSET
	DB	' DSK- '
;
DISK:	EQU	$+OFFSET
	DB	20H,20H
	DB	' TRK- '
;
TRACK:	EQU	$+OFFSET
	DB	20H,20H
	DB	' SEC- '
;
SECT:	EQU	$+OFFSET
	DB	20H,20H
	DB	' DMA- '
;
DMA:	EQU	$+OFFSET
	DB	20H,20H,20H,20H
	DB	' OPCD-  '
;
OPCD:	EQU	$+OFFSET
	DB	20H,0A0H
;
;
;TEMP VALUE STORAGE
;
TDISK:	EQU	$+OFFSET
	DB	0
TTRACK: EQU	$+OFFSET
	DB	0
TSECT:	EQU	$+OFFSET
	DB	0
TDMA:	EQU	$+OFFSET
	DB	0,0
TOPCD:	EQU	$+OFFSET
	DB	0
;
;
PROEND: EQU	$
;
;
	END	START
