;***************************************;
;	EXPANDED SECTOR PATCH UTILITY	;
;***************************************;
;
;MODIFIED FOR POLYMORPHICS VTI PLUS DISPLAY CLARITY IMPROVED
;IN NOV, 1978 BY:	JIM GAGNE, M.D.
;			DATAMED RESEARCH
;			515 DALEHURST AVE
;			LOS ANGELES, CA 90024
;GENERALIZED FOR ALL MEMORY-MAPPED VIDEO, JIM GAGNE, OCT '79
;
;INSTRUCTIONS FOR USE:
;THIS DISPLAYS CONTENTS OF ANY SELECTED SECTOR, TRACK, AND DRIVE.
;AT START, YOU CAN CHOOSE 1ST SECTOR, TRACK, AND/OR DRIVE (INITIALIZED
;TO 00) BEFORE ANY READ IS DONE.
;
;SUMMARY OF COMMANDS:
;S	SELECT SECTOR IN HEX.  MUST TERMINATE WITH ANY CONTROL CHAR-
;	ACTER, EG <RETURN>.  A SPACE AUTOMATICALLY PUTS YOU INTO TRACK:
;T	SELECT TRACK IN HEX.  WORKS IDENTICALLY TO SECTOR,
;	EXCEPT SPACE PUTS YOU IN DRIVE SELECT:
;D	SELECT DRIVE, 1 THRU 4.
;G	SELECT CP/M GROUP, 0 THRU 242.	0 AND 1 ARE DIRECTORY.
;	A SPACE PUTS YOU INTO FRACTION.
;F	SELECT "FRACTION," WHICH IS RELATIVE SECTOR WITHIN A
;	GROUP (0 THRU 7 FOR A TOTAL OF 8)
;
;R	READ SECTOR PER PREVIOUSLY SELECTED TRACK, DRIVE, SECTOR
;W	WRITE CORRECTED INFORMATION INTO SELECTED TR, DR, SECTR
;
;+ OR LF READ NEXT SECTOR
;-	READ PREVIOUS SECTOR
;I	STEP HEAD IN (NEXT TRACK) AND READ SAME SECTOR #
;O	STEP HEAD OUT (PREVIOUS TRACK) AND READ SECTOR
;B	READ GROUP BEFORE THIS ONE, SAME "FRACTION."
;Z	READ GROUP AFTER THIS ONE.
;P	READ PREVIOUS "FRACTION."
;N	READ NEXT "FRACTION."
;
;M	MAP THE CURRENT GROUP IN ASCII: THIS FILLS THE TV SCREEN
;	WITH THE CONTENTS OF THE ENTIRE GROUP IN LIVING BLACK 
;	AND WHITE.  PRESS B/Z TO READ PREVIOUS/NEXT GROUP; ANY
;	OTHER CHARACTER PUTS YOU BACK INTO THE REGULAR DISPLAY MODE.
;A	WRITE ASCII INTO SELECTED AREA OF BUFFER.  WILL ASK FOR
;	STARTING BYTE #.  TERMINATE W/ ANY CTL CHAR.
;H	WRITE HEX DATA INTO SELECTED AREA OF BUFFER, SIMILAR TO A
;	EXCEPT THAT SPACE INCORPORATES ANY CHANGES THAT WERE
;	MADE (OR NONE IF NONE) AND GOES ON TO NEXT BYTE.
;L	LOAD DISK BUFFER CONTENTS INTO SEPARATE BUFFER NOT AFFECTED
;	BY DISK I/O, FOR LATER WRITING TO ANOTHER SECTOR.
;U	UNLOAD SEPARATE BUFFER CONTENTS BACK INTO DISK BUFFER, FOR
;	SAVING ON DISK.
;C	REINITIALIZE XSPAT AND START AGAIN
;Q OR CTL C
;	BACK TO CPM
;
;
	ORG	100H
 
;****
; MISC. EQUATES
;****
 
TBUF	EQU	0080H
VDMLC	EQU	0E800H
VDMLN	EQU	64
VDMPG	EQU	8
FF	EQU	12	;FORMFEED
BLANK	EQU	020H	;VTI SPACE CHARACTER
VTIADJ	EQU	0	;MUST ADD THIS TO GET VALID CHAR WITH VTI
CURSHOME EQU	1AH	;HOME CRT CURSOR CHAR, USED BY MY CBIOS
COL	EQU	48H	;ADDRESS OF COLUMN NO. FOR CRT
LIN	EQU	49H	;ADDRESS OF LINE NUMBER FOR VIDEO DISPLAY DRIVER
;*****
; OBTAIN BIOS VECTORS
;*****
VECTRS: JMP	GETVEC
	DS	42
WBOOTE	EQU	VECTRS+3
CSTS	EQU	VECTRS+6
CI	EQU	VECTRS+9
CO	EQU	VECTRS+12
LO	EQU	VECTRS+15
PO	EQU	VECTRS+18
RI	EQU	VECTRS+21
HOME	EQU	VECTRS+24
SELDSK	EQU	VECTRS+27
SETTRK	EQU	VECTRS+30
SETSEC	EQU	VECTRS+33
SETDMA	EQU	VECTRS+36
READ	EQU	VECTRS+39
WRITE	EQU	VECTRS+42
GETVEC: LXI	D,WBOOTE
	LHLD	1
	MVI	B,42
GETVE1: MOV	A,M
	STAX	D
	INX	H
	INX	D
	DCR	B
	JNZ	GETVE1
;
 
;****
; MAIN PROGRAM
;****

MAIN:	LXI	SP,STACK	;SET STACK
	MVI	C,FF
	CALL	CO	;RESETS MY VIDEO DRIVER
	LXI	H,TBUF	;CLEAR BUFFER TO SPACES
	MVI	B,128	;BUFFER SIZE
	MVI	A,' '
CL3:	MOV	M,A
	INX	H
	DCR	B
	JNZ	CL3
	LXI	D,MSG1
	LXI	H,VDMLC
	MVI	B,64
	CALL	MOVTG	;MOV MSG1 TO SCREEN
	SUB	A
	STA	CURDK	;SET DISK TO DRIVE 0
	CALL	HOME	;RESTORE HEAD
	XRA	A
	STA	CURTK	;SET CURTK BYTE
	INR	A
	STA	CURSC	;SET CURRENT SECTOR
	LXI	H,VDMLC+VDMLN
	LXI	D,MSG2
	MVI	B,64
	CALL	MOVTG
	JMP	LOOP1
LOOP:	CALL	DSPLY	;DISPLAY PARAMETERS
LOOP1:	CALL	CONIN	;READ CONSOLE
	CPI	'A'
	JC	LOOP2
	ANI	5FH
LOOP2:	MVI	H,BLANK ;CLEAR ERROR FLAG
	MVI	L,BLANK
	SHLD	VDMLC+(15*VDMLN)
	LXI	H,CMDTB ;POINT TO COMMAND TABLE
	MVI	C,NCMDS ;NUMBER OF COMMANDS
CMLP:	CMP	M	;COMMAND FOUND?
	JZ	CMOK
	INX	H
	INX	H
	INX	H
	DCR	C	;ANY COMMANDS LEFT?
	JNZ	CMLP	;YES, KEEP LOOKING
ERR:	LXI	H,VDMLC+(15*VDMLN)
	MOV	M,A
	INX	H
	MVI	M,'?'+80H
	JMP	LOOP
CMOK:	INX	H
	MOV	E,M
	INX	H
	MOV	D,M
	XCHG
	LXI	D,LOOP
	PUSH	D
	PCHL
 
CONIN:	PUSH	B
	CALL	CI
	POP	B
	ANI	7FH
	CPI	3
	JZ	0
	RET
 
;****
; DISPLAY ROUTINE
;****
;
;####################################
;	<<<<NOTE>>>>
;MAKE SURE YOU DELETE FIRST 3 LINES IF YOU HAVE NO CURSOR PROBLEM!
;####################################
DSPLY:	MVI	H,15	;LINE 15
	MVI	L,8	;COLUMN 8
	SHLD	COL	;WE'VE MOVED CURSOR TO LINE 15, COL 8
	LXI	H,VDMLC
	MVI	B,VDMLN*3
	MVI	C,4
BLK15:	CALL	BLANKIT
	DCR	C
	JNZ	BLK15	;BLANK 15 LINES OF CRT SCREEN.
	MVI	B,VDMLN
	LXI	H,VDMLC
	LXI	D,PROMPT
	CALL	MOVTG
	LXI	D,TBUF
	LXI	H,VDMLC+(3*VDMLN)
	MVI	B,80H
	CALL	MOVE
	LXI	H,VDMLC+VDMLN
	LXI	D,MSG2
	MVI	B,64	;MOVE MESSAGE TO SCREEN
	CALL	MOVTG
	LXI	H,VDMLC+(2*VDMLN)
	LXI	D,ASCSCALE	;ASCII SCALE COUNTER
	MVI	B,64
	CALL	MOVTG
	LXI	H,VDMLC+(6*VDMLN)
	LXI	D,HEXSCALE	;HEX AREA SCALE MARKER
	MVI	B,64
	CALL	MOVTG
	LXI	H,VDMLC+VDMLN+OF1	;OFFSET TO FIELD1
	LDA	CURSC
	CALL	HXO	;DISPLAY SECTOR NUMBER
	LXI	H,VDMLC+VDMLN+OF2	;OFFSET TO FIELD2
	LDA	CURTK
	CALL	HXO	;DISPLAY CURTK NUMBER
	LXI	H,VDMLC+VDMLN+OF3	;OFFSET TO FIELD3
	LDA	CURDK
	CALL	HXN	;DISPLAY DISK NUMBER
	LXI	H,VDMLC+VDMLN+OF4
	IN	0F8H	;DISK STATUS
	CALL	HXO
	CALL	GETLSN	;GET LOGICAL SECTOR NO. FOR NEXT ROUTINE.
	CALL	GETGRP	;DERIVES GROUP AND "FRACTION" NO. FROM
			;TRACK AND SECTOR, FOR PURPOSES OF DISPLAY.
	LXI	H,VDMLC+VDMLN+OFGRP
	LDA	GROUP
	INR	A	;IF 0FFH, MEANS WE'RE IN TRACK 0 OR 1.
	JNZ	NUMBIT	;ELSE GO GET GROUP/RECORD NO.
	MVI	B,'-'+VTIADJ
	MOV	M,B	;PUT BLANKS TO SIGNIFY NO VALID NO.
	INX	H
	MOV	M,B
	LXI	H,VDMLC+VDMLN+OFFRC
	MOV	M,B	;SAME FOR "FRACTN"
	INX	H
	MOV	M,B
	JMP	WHEAD
NUMBIT:	DCR	A
	CALL	HXO
	LXI	H,VDMLC+VDMLN+OFFRC
	LDA	FRACTN
	CALL	HXO
WHEAD:	LXI	H,VDMLC+(7*VDMLN)	;NOW WRITE LINE HEADINGS
	MVI	A,'0'+VTIADJ	;FOR HEX DISPLAYS, '00' THRU '80'
	LXI	D,VDMLN-1
	MOV	B,A
	MVI	C,8
DLLP:	MOV	M,A
	INR	A
	INX	H
	MOV	M,B
	DAD	D
	DCR	C
	JNZ	DLLP
	LXI	H,VDMLC+(7*VDMLN)+5
	LXI	D,TBUF	;POINT TO BUFFER
	MVI	B,8	;LINE COUNT
	PUSH	B
LINELP: CALL	WRITLINE	;NOW WRITE OUT HEX LINE
	POP	B
	DCR	B
	RZ
	PUSH	B
	LXI	B,13
	DAD	B
	JMP	LINELP
;
WRITLINE:
	MVI	C,16
WL1:	MVI	B,4
WL2:	LDAX	D
	PUSH	B
	CALL	HXO
	POP	B
	MVI	M,BLANK
	INX	H
	INX	D
	DCR	C
	RZ
	DCR	B
	JNZ	WL2
	MVI	M,BLANK
	INX	H
	JMP	WL1
;
BLANKIT:MVI	M,BLANK
	INX	H
	DCR	B
	JNZ	BLANKIT
	RET

;****
; READ ROUTINE
;****
 
READR:	CALL	SETUP
	CALL	READ
	RET

SETUP:	LXI	B,TBUF
	CALL	SETDMA
	LDA	CURDK
	MOV	C,A
	CALL	SELDSK
	LDA	CURSC
	MOV	C,A
	CALL	SETSEC
	LDA	CURTK
	MOV	C,A
	CALL	SETTRK
	RET
 
WRITR:	CALL	SETUP
	LHLD	1	;GET BIOS ADDR
	MVI	L,2AH	;WRITE VECTOR
	PCHL

NEXTR:	CALL	NXSEC	;BUMP TO NEXT SECTOR
	CC	NXTRK	;BUMP TO NEXT CURTK
	MVI	A,'+'
	JC	ERR	;ERROR
	CALL	READR
	RET

PREVR:	CALL	PVSEC	;BUMP TO PREV. SECTOR
	CC	PVTRK
	MVI	A,'-'
	JC	ERR
	CALL	READR
	RET

HDOUT:	CALL	PVTRK	;DECREMENT CURTK
	CALL	READR	;READ SECTOR
	RET		;EXIT

HDIN:	CALL	NXTRK	;INCREMENT CURTK
	CALL	READR	;READ SECTOR
	RET		;MOVE HEAD

NXSEC:	LDA	CURSC
	CPI	26	;END OF CURTK
	JNC	NXS2	;YES
	INR	A
	STA	CURSC
	XRA	A
	RET
NXS2:	MVI	A,01
	STA	CURSC
	STC
	RET

NXTRK:	LDA	CURTK
	CPI	76
	CMC
	RC		;ERROR
	INR	A
	STA	CURTK
	RET

PVSEC:	LDA	CURSC
	CPI	01+1
	JC	PVS2
	DCR	A
	STA	CURSC
	XRA	A
	RET
PVS2	MVI	A,26
	STA	CURSC
	STC
	RET

PVTRK:	LDA	CURTK
	CPI	00+1
	RC
	DCR	A
	STA	CURTK
	RET
;
NXTFR:	CALL	SNFRAC
	CC	SNGRP
	MVI	A,'N'
	JC	ERR
	CALL	GETTS
	JMP	READR
;
PREVFR: CALL	SPFRAC
	CC	SPGRP
	MVI	A,'P'
	JC	ERR
	CALL	GETTS
	JMP	READR
;
BEFGRP: CALL	SPGRP
	MVI	A,'B'
	JC	ERR
	CALL	GETTS
	JMP	READR
;
ZGRP:	CALL	SNGRP
	MVI	A,'Z'
	JC	ERR
	CALL	GETTS
	JMP	READR
;
SNGRP:	LDA	GROUP	;SUBROUTINE FOR NEXT GROUP
	CPI	242	;MAX # GROUPS
	CMC
	RC
	INR	A
	STA	GROUP
	RET
;
SPGRP:	LDA	GROUP	;SUBROUTINE FOR PREV. GROUP
	CPI	1	;DON'T DCR < 0
	RC
	DCR	A
	STA	GROUP
	RET
;
SNFRAC: LDA	FRACTN
	CPI	7
	JNC	SNF2
	INR	A
	STA	FRACTN
	ORA	A
	RET
SNF2:	SUB	A
	STA	FRACTN
	STC
	RET
;
SPFRAC: LDA	FRACTN	;SUBROUTINE TO INCREMENT "FRACTION"
	DCR	A
	JM	SPF2
	STA	FRACTN
	ORA	A
	RET
SPF2:	MVI	A,7
	STA	FRACTN
	STC
	RET
;
NWGRP:	LXI	H,VDMLC + VDMLN + OFGRP
	CALL	GETEM
	JC	NWGP2	;NO CHAR ENTERED, JUSP DELIMITR
	MOV	A,B
	CPI	243	;242 GROUPS MAX
	JNC	NWGRP
	STA	GROUP
NWGP2:	LDA	GROUP
	DCX	H
	CALL	HXO
	MOV	A,C
	CPI	20H
	JZ	NWFRAC
	CALL	GETTS
	JMP	READR
;
NWFRAC: LXI	H,VDMLC + VDMLN + OFFRC
	CALL	GETEM
	JC	NWFR2
	MOV	A,B
	CPI	8
	JNC	NWFRAC
	STA	FRACTN
NWFR2:	LDA	FRACTN
	DCX	H
	CALL	HXO
	CALL	GETTS
	CALL	READR
	RET
;
;
;TRACK = ((GROUP * 8) + GROUP RECORD NO.) DIV 26 + 2
GETTS:	LHLD	GROUP	;LOW BYTE IS GROUP #
	MVI	H,0
	DAD	H
	DAD	H
	DAD	H
	XCHG
	LHLD	FRACTN
	MVI	H,0
	DAD	D	;HL NOW CONTAINS TOTAL SECTOR NO.,
;STARTING FROM TRACK 2
	LXI	D,-26
	SUB	A
DIV26:	DAD	D
	INR	A
	JC	DIV26
	LXI	D,26
	DAD	D	;L NOW CONTAINS LOGICAL SECTOR NO.(LSN),
;0 TO 25
	INR	A	;NOW TRACK NO CORRECT (+2)
	STA	CURTK
	MOV	A,L
;
;NOW PHYSICAL SECTOR NO. = LSN * 6 MOD 26 +1 (+1 IF PSN > 12)
	ADD	A
	MOV	B,A
	ADD	A
	ADD	B	;A = A*6
	MVI	B,26	;B IS DIVISOR
MOD26:	SUB	B
	JNC	MOD26
	ADD	B	;A = A*6 MOD 26
	INR	A
	MOV	B,A
	MOV	A,L
	CPI	13
	JC	NOINC
	INR	B	;B NOW W/ CORRECT PSN
NOINC:	MOV	A,B
	STA	CURSC
	RET
;
;
;
;LSN = (13 IF PSN EVEN; DCR PSN IF EVEN; ELSE LSN = 0) +
;  PSN DIV 6 + PSN MOD 6.  THEN DCR LSN IF REMAINDER 1, AND ADD
;  6 IF REMAINDER IS 3.
GETLSN: LDA	CURSC
	MOV	B,A
	MVI	C,0	;C = LSN
	RAR
	JC	PSNEVN
	DCR	B
	MVI	C,13
PSNEVN: MOV	A,B
	MVI	B,6
DIV6:	SUB	B
	INR	C
	JNC	DIV6
	ADD	B	;A NOW W/ CORRECT REMAINDER
	DCR	C
	MVI	B,0
	CPI	1
	JNZ	NDECC
	DCR	C
NDECC:	CPI	3
	JNZ	NADD6
	MVI	B,6
NADD6:	ADD	C
	ADD	B
	STA	LSN
	RET
;
;GROUP = ((TRACK - 2)*26 + LSN) DIV 8
;FRACTION =	    "		MOD 8
GETGRP: LDA	CURTK
	DCR	A
	DCR	A
	JM	INCPM	;SKIP IF IN BOOT AREA
	MOV	L,A
	MVI	H,0
	DAD	H	;HL*2
	PUSH	H
	DAD	H
	DAD	H	;HL*8
	PUSH	H
	DAD	H	;HL*16
	POP	D
	DAD	D	;HL*24
	POP	D
	DAD	D	;HL*26
	XCHG
	LHLD	LSN
	MVI	H,0
	DAD	D
;NOW DIVIDE BY 8
	LXI	D,-8
	SUB	A
DIV8:	DAD	D
	INR	A
	JC	DIV8
	DCR	A	;NOW CORRECT QUOTIENT
	STA	GROUP
	LXI	D,8
	DAD	D	;L W/ CORRECT REMAINDER
	MOV	A,L
	STA	FRACTN
	RET
INCPM:	MVI	A,0FFH
	STA	GROUP
	RET
;
CLRTV:	LXI	H,VDMLC ;POINT TO VDM MEMORY
	MVI	B,VDMPG ;# PAGES IN VDM
	MVI	A,BLANK
CLR:	MVI	C,00
CL2:	MOV	M,A
	INX	H
	DCR	C
	JNZ	CL2
	DCR	B
	JNZ	CLR
	RET
;
MOVTG:	LDAX	D
	ORI	VTIADJ
	MOV	M,A
	DCR	B
	INX	H
	INX	D
	JNZ	MOVTG
	RET
 
HXO:	MOV	B,A	;SAVE BYTE IN B
	RRC
	RRC
	RRC
	RRC		;GET HI ORDER 4 BITS
	CALL	HXN	;CONVERT TO HEX ASCII
	MOV	A,B	;GET BYTE AGAIN

HXN:	ANI	0FH		;GET 4 BITS
	ORI	030H + VTIADJ	;CONVERT TO ASCII
	CPI	03AH + VTIADJ	;A-F?
	JC	HXN1		;NO, CONTINUE
	ADI	07		;COMPENSATE
HXN1:	MOV	M,A		;STORE BYTE
	INX	H
	RET

MOVE:	LDAX	D
	CPI	20H
	JNC	MOV1
	MVI	A,'.'
MOV1:	CPI	80H
	JC	MOV2
	MVI	A,'.'
MOV2:	ORI	VTIADJ
	MOV	M,A
	INX	H
	INX	D
	DCR	B
	JNZ	MOVE
	RET
 
HXI:	LXI	B,0
	CALL	HXC
	RC
	MOV	B,A
HXI1:	CALL	HXC
	CMC
	RNC
	MOV	C,A
	MOV	A,B
	ADD	A
	ADD	A
	ADD	A
	ADD	A
	ADD	C
	MOV	B,A
	JMP	HXI1

HXC:	CALL	CONIN
	MOV	C,A
	CPI	'0'
	RC
	CPI	'9'+1
	JNC	HXA
	ORI	VTIADJ
	MOV	C,M
	DCX	H
	MOV	M,C
	INX	H
	MOV	M,A
	ANI	0FH
	RET
HXA:	ANI	5FH
	CPI	'A'
	JC	HXC
	CPI	'F'+1
	JNC	HXC
	ORI	VTIADJ
	MOV	C,M
	DCX	H
	MOV	M,C
	INX	H
	MOV	M,A
	SUI	37H
	ANI	0FH
	RET

GETEM:	MVI	M,'?'+80H
	INX	H
	MVI	M,'?'+80H
	CALL	HXI
	RC
	MOV	A,B
	ANA	A
	RET

NWDSK:	LXI	H,VDMLC+VDMLN+OF3
	CALL	GETEM
	JC	NWDS1
	MOV	A,B
	CPI	2
	JNC	NWDSK
	STA	CURDK
NWDS1:	LDA	CURDK
	DCX	H
	CALL	HXO
	CALL	READR
	RET

NWTRK:	LXI	H,VDMLC+VDMLN+OF2
	CALL	GETEM
	JC	NWTR2
	MOV	A,B
	CPI	4DH
	JNC	NWTRK
	STA	CURTK
NWTR2:	LDA	CURTK
	DCX	H
	CALL	HXO
	MOV	A,C
	CPI	20H
	JZ	NWDSK
	CALL	READR
	RET

NWSEC:	LXI	H,VDMLC+VDMLN+OF1
	CALL	GETEM
	JC	NWSC2
	XRA	A
	ADD	B
	JZ	NWSEC
	CPI	1BH
	JNC	NWSEC
	STA	CURSC
NWSC2:	LDA	CURSC
	DCX	H
	CALL	HXO
	MOV	A,C
	CPI	20H
	JZ	NWTRK
	CALL	READR
	RET

GETBNO: LXI	H,VDMLC+(15*VDMLN)
	LXI	D,MSGI
	MVI	B,MSGILEN
	CALL	MOVTG
	CALL	GETEM
	RC
	MOV	A,B
	CPI	128
	JNC	GETBNO
	ORA	A
	JM	GETBNO
	STA	BYTENO
	MVI	B,MSGILEN+3
	LXI	H,VDMLC+(15*VDMLN)+32
	CALL	BLANKIT
	ANA	A
	RET

HEXPAT: CALL	GETBNO
	RC
HEXPA0: LDA	BYTENO
	MOV	C,A
	MVI	B,0
	LXI	H,TBUF
	DAD	B
	XCHG
	ADD	A
	PUSH	PSW
	ANI	63	;MASK OFF HIGHER BITS
	LXI	H,HEXTABLE
	MOV	C,A
	MVI	B,0
	DAD	B
	MOV	C,M
	INX	H
	MOV	B,M
	LXI	H,VDMLC+(7*VDMLN)
	DAD	B
	POP	PSW
	JP	FINDBYT1 ;JUMP IF BYTENO < 64
	LXI	B,VDMLN*4
	DAD	B	;SHORTENS THE TABLE SOME
FINDBYT1: ADD	A	;NOW SEE IF 32 >= BYTENO >= 63 OR
	JP	FINDBYT2 ;BYTENO >= 96; IF NOT,SKIP
	LXI	B,VDMLN*2	;ELSE MOVE DOWN 2 MORE LINES
	DAD	B
FINDBYT2: CALL	GETEM
	JC	HEXPA2
	MOV	A,B
	STAX	D
HEXPA2: LDAX	D
	DCX	H
	CALL	HXO
	MOV	A,C
	CPI	' '
	RNZ
	INX	D
	LDA	BYTENO
	INR	A
	CPI	128
	RNC
	STA	BYTENO
	JMP	HEXPA0

ASCPAT: CALL	GETBNO
	RC
	LDA	BYTENO
	MOV	C,A
	MVI	B,0
	LXI	H,TBUF
	DAD	B
	XCHG
	LXI	H,VDMLC+(3*VDMLN)
	DAD	B
ASCPA1: MVI	M,'?'+80H
	CALL	CONIN
	ORA	A
	JZ	ASCPZ	;SKIP TO NEXT CHAR IF NULL
	CPI	20H
	RC
	STAX	D
ASCPZ:	LDAX	D
	ORI	VTIADJ
	MOV	M,A
	INX	H
	INX	D
	LDA	BYTENO
	INR	A
	CPI	128
	RNC
	STA	BYTENO
	JMP	ASCPA1
;
EXIT:	CALL	CLRTV
	JMP	0
;
MAP:	SUB	A
	STA	FRACTN
	LXI	H,VDMLC
ASCLP:	PUSH	H
	CALL	GETTS
	CALL	READR
	POP	H
	LXI	D,TBUF
	MVI	B,80H
	CALL	MOVE
	LDA	FRACTN
	CPI	7
	JNC	ADONE
	INR	A
	STA	FRACTN
	JMP	ASCLP
ADONE:	CALL	CI
	CPI	'B'
	JNZ	NOTB
	LDA	GROUP
	DCR	A
	RM
	STA	GROUP
	JMP	MAP
NOTB:	CPI	'Z'
	RNZ
	LDA	GROUP
	CPI	242
	RNC
	INR	A
	STA	GROUP
	JMP	MAP
;
LOAD:	LXI	H,TBUF
	LXI	D, BUFFR
MOVRIT:	MVI	B,80H
MOVR0:	MOV	A,M
	STAX	D
	INX	H
	INX	D
	DCR	B
	JNZ	MOVR0
	RET
;
UNLOAD:	LXI	H,BUFFR
	LXI	D,TBUF
	JMP	MOVRIT
;
CMDTB:	DB	'R'
	DW	READR
	DB	'W'
	DW	WRITR
	DB	'A'
	DW	ASCPAT
	DB	'H'
	DW	HEXPAT
	DB	'+'	;READ NEXT SECTOR
	DW	NEXTR
	DB	0AH
	DW	NEXTR
	DB	'-'	;READ PREV SECTOR
	DW	PREVR
	DB	'I'	;STEP HEAD IN
	DW	HDIN
	DB	'O'	;STEP HEAD OUT
	DW	HDOUT
	DB	'B'	;READ GROUP BEFORE THIS ONE
	DW	BEFGRP
	DB	'Z'	;READ GROUP AFTER THIS ONE
	DW	ZGRP
	DB	'P'	;READ PREVIOUS "FRACTION"
	DW	PREVFR
	DB	'N'	;READ NEXT "FRACTION"
	DW	NXTFR
	DB	'M'	;ASCII MAP OF GROUP
	DW	MAP
	DB	'S'	;SPECIFIC SECTOR
	DW	NWSEC
	DB	'T'
	DW	NWTRK	;SPECIFIC TRACK
	DB	'D'	;SELECT DISK DRIVE
	DW	NWDSK
	DB	'G'	;SPECIFIC GROUP NO.
	DW	NWGRP
	DB	'F'	;SPECIFIC "FRACTION" (REL SECTOR OF GROUP)
	DW	NWFRAC
	DB	'L'	;LOAD SPARE BUFFER W/ CONTENTS DISK BUFFER
	DW	LOAD
	DB	'U'	;UNLOAD SPARE BUFFER CONTENTS INTO DISK BUFFER
	DW	UNLOAD
	DB	'C'	;CLEAR ALL AND RESTART EXAM
	DW	MAIN
	DB	'Q'	;QUIT (EXIT TO CP/M)
	DW	EXIT
NCMDS	EQU	($-CMDTB)/3
 
MSG1:	DB	' XSPAT VERSION 2.0   '
	DB	'                   '
	DB	'                        '
MSG2:	DB	'SECTOR    '
MSG2A:	DB	'TRACK    '
MSG2B:	DB	'DRIVE   '
MSG2C:	DB	' STATUS    '
MSG2D:	DB	'   GROUP   /'
MSG2E:	DB	'RECORD("F")    '
MSGEND	EQU	$
	DB	'                   '
MSGI:	DB	'                                 BYTE # '
MSGILEN EQU	$-MSGI
OF1	EQU	(MSG2A-MSG2)-3
OF2	EQU	(MSG2B-MSG2)-3
OF3	EQU	(MSG2C-MSG2)-2
OF4	EQU	(MSG2D-MSG2)-3
OFGRP	EQU	(MSG2E-MSG2)-3
OFFRC	EQU	(MSGEND-MSG2)-3
;
PROMPT	DB	'(+/-);    (I/O); <C)LR;M)AP;Q)UIT;R)EAD> '
	DB	'(B/Z); (P/N);  <W)RITE>  '
ASCSCALE:	DB	'0       ,       1       ,       2'
	DB	'       ,       3       ,      4'
HEXSCALE:
	DB	'      0  1  2  3   4  5  6  7   '
	DB	'8  9  A  B   C  D  E  F            '
;
HEXTABLE:	;THIS IS A TABLE OF BYTE DISPLACEMENTS FOR
		;HEX REPLACEMENT ROUTINE.
	DW	5
	DW	8
	DW	11
	DW	14
	DW	18
	DW	21
	DW	24
	DW	27
	DW	31	;9TH BYTE IN A LINE
	DW	34
	DW	37
	DW	40
	DW	44
	DW	47
	DW	50
	DW	53
	DW	5+64
	DW	8+64
	DW	11+64
	DW	14+64
	DW	18+64
	DW	21+64
	DW	24+64
	DW	27+64
	DW	31+64
	DW	34+64
	DW	37+64
	DW	40+64
	DW	44+64
	DW	47+64
	DW	50+64
	DW	53+64
CURSC:	DB	00	;CURRENT SECTOR
CURTK:	DB	00	;CURRENT TRACK
CURDK:	DB	00	;CURRENT DISK
GROUP:	DB	00	;CURRENT GROUP
FRACTN: DB	00	;CURRENT "FRACTION" (RELATIVE SECTOR NO.
LSN:	DB	00	;STORAGE FOR LOGICAL SECTOR NO.
			;WITHIN GROUP)
BYTENO: DB	0
BUFFR:	DS	80H
	DS	64
STACK	EQU	$
	END	100H
