;*****************************************************************
; DIRECT DISK DUMP V1.0 850830 PB. VERSION WITH OWN DISK DRIVERS .
; Uses direct sector read and write; no de-blocking. 
; May be altered for none-zero sector skews by adjusting table. 
;*****************************************************************
;
; LIBRARY FILES REFERENCED:  DISK.GEN
;
; May be assembled with HISOFT GEN-80 assembler, or 
; modified to suit most other Z80 assemblers easily. 
; Only one macro (MCAL) is used: replace with RST 8 
; followed by DEFB <call no.> for non-macro assemblers.
;
;
MCAL:	MACRO	@PRZ
	RST 8		; ROM CALL
	DEFB	@PRZ
	ENDM
;
; Useful Equates:
;
CR:	EQU	0DH
LF:	EQU	0AH
HOME:	EQU	01EH	; CUR. HOME
CLS:	EQU	016H	; CLEAR TO END
ESC:	EQU	01BH	; ESCAPE 
BOOT:	EQU	0000H
CURSR:	EQU	0FB4AH	; CURSOR
;
NSECS:	EQU	10	; 10 SECTRS/TRACK 
NTRKS:	EQU	40 	; NO. TRACKS
;
; Einstein MOS calls:
;
ZMOD:	EQU	8CH	; MODIFY MEMORY
TBLATE:	EQU	93H	; TABULATE
ZKEYIN:	EQU	9CH	; GET I/P
ZGETLN:	EQU	9DH	; GET I/P LINE TO [DE]
ZOUTC:	EQU	9EH	; O/P A
ZRSECT:	EQU	0A2H	; READ 200H BYTES INTO FE00H
ZH2IN:	EQU	0ADH	; GET 2 HEX DIGITS FROM [DE]
ZHMDSC:	EQU	0AFH	; HOME DISK
ZFDRST:	EQU	0BDH	; DISC RESET
ZPRM:	EQU	0CFH	; PRINT MESSAGE
ZPRA:	EQU	0ABH	; PRINT OUT <A>, NO SPACE
ZCRLF:	EQU	0A6H	; O/P CRLF
ZPINIT:	EQU	0C0H	; INIT. PSG
HSTDSC:	EQU	0FB50H	; DRIVE
HSTTRK:	EQU	0FB51H	; TRACK (0-27H)
HSTSEC:	EQU	0FB52H	; SECTOR (0-9)
HSTDMA:	EQU	0FB53H	; DISC BUFFER PTR.
DBUFF:	EQU	0FE00H	; USUAL 200H BYTES 
;
; Begin the program:
;
	ORG	100H
	JP	START
SKEW:	DEFS	2	; SECTOR SKEW TEMP. 
STACK:	DEFS	30H	; OUR STACK
;
START:	LD (STACK),SP	; SAVE SP
	LD SP,START
	MCAL ZPRM	; SIGN - ON
	DEFM "Einstein Direct Disc Editor V1.0 "
	DEFB CR,LF+80H
	CALL INITT 	; INIT. TRACK 0
RSLP:	CALL INITS	; INIT. SECTORS 	
	CALL GETDR	; DRIVE ??
	MCAL ZPRM 
	DEFB HOME,CLS,LF	; SIGN-ON
	DEFB CR,LF
	DEFM "Seeking ... "
	DEFB CR,LF+80H
;
;
LOOP:	MCAL ZCRLF 
	CALL STATUS	; WHATS UP
	MCAL ZCRLF
;
	CALL RDSECT	; READ  200H BYTES 
	JR Z,LPRNT	; NO ERROR 
	MCAL ZPRM 	; ELSE PRINT ERROR
	DEFM "Read Error:"
	DEFB 20H+80H
	CALL DSCERR
	MCAL ZCRLF 
	JR RSLP		; RETRY AFTER ERROR 
;	
LPRNT:	CALL DISPF	; PRINT FIRST HALF OF SECTOR
	MCAL ZCRLF 
	MCAL ZPRM 
	DEFM " <CR>... or M to Modify.
	DEFB 20H+80H
  	CALL CMND	; USER READY?
	CP "M"		; MODIFY?
	JR NZ,LD1
	LD HL,0600H	; SET CURSOR
	LD (CURSR),HL
	LD HL,0FE00H	; START OF BUFFER 
	MCAL ZMOD
	LD HL,0600H	; RESET CURSOR
	LD (CURSR),HL
	JR LPRNT	; REPEAT THIS SECTOR 
LD1:	MCAL ZCRLF 	; GO ON 
;
	CALL STATUS	; REDISPLAY STATUS
	MCAL ZCRLF 
LD2:	CALL DISPS	; DISPLAY SECOND HALF OF SECTOR
	MCAL ZPRM 
	DEFB CR,LF
	DEFM " R to Restart,M to Modify, W to Write, <ESC> to quit."
	DEFB 20H+80H
	CALL CMND	; WAIT FOR IT!
	CP "R"		; QUIT?
	JP Z,RSLP	; YES, THATS IT
	CP "M"		; MOD?
	JR NZ,LDW	; NO. SKIP M
	LD HL,0600H	; SET CURSOR
	LD (CURSR),HL
	LD HL,0FF00H	; NEXT BIT
	MCAL ZMOD 
	LD HL,0600H	; RESET CURSOR
	LD (CURSR),HL
	JR LD2		; REPEAT THIS 
LDW:	CP "W"		; WRITE?
	JR NZ,LP1	; NO, SKIP WRITE 
	MCAL ZCRLF	; TIDY UP 
	MCAL ZPRM 
	DEFM "Writing sector to disk."
	DEFB CR,LF+80H
	CALL WRSECT
	JR Z,LP1	; NO ERROR
	MCAL ZPRM
	DEFM "Write Error:"
	DEFB 20H+80H
	CALL DSCERR 
	MCAL ZCRLF
;  	
LP1:	CALL NEXT	; NEXT BLOCK ADDRESS
	MCAL ZCRLF 
	JP LOOP
;
DONE:	MCAL ZFDRST	; CLEAN UP THE MESS
	LD SP,(STACK)	; THATS ALL FOLKS!
	RET 
;
INITT:	XOR A		; ZER0
	LD (HSTTRK),A	; TRACK = 0
	RET 
INITS:	LD A,(SK3TBL)	; FIRST SECTOR FROM TABLE
	LD (HSTSEC),A	; SECTOR = 0
	LD HL,DBUFF	; INIT. HDMA
	LD (HSTDMA),HL
	LD HL,0		; SKEW COUNT = 0 
	LD (SKEW),HL
	RET
;
; Display 100H bytes using TABULATE:
DISPF:	LD HL,DBUFF		; START
	LD DE,DBUFF+0FFH	; FINISH
	JR DISP
DISPS:	LD HL,DBUFF+100H	; START 
	LD DE,DBUFF+1FFH	; FINISH
DISP:	LD BC,10H		; NO. COLS.
	MCAL TBLATE
	MCAL ZCRLF		; CLEAN UP
	RET
;
; ASK FOR DRIVE :
GETDR:	MCAL ZPRM 
	DEFB CR,LF
GMS:	DEFM "Which Drive (0 - 3) ? "
	DEFB 20H+80H 
GME:	MCAL ZKEYIN	; GET ANSWER
	CP CR		; DEFAULT?
	JR NZ,GET1	; NO
	LD A,(0004)	; GET IT
	JR GEND
GET1:	MCAL ZOUTC	; ECHO 
	LD B,A		; SAVE ANSWER
GT:	MCAL ZKEYIN	; WAIT FOR OP.
	CP CR 
	JR NZ,GT
	LD A,B		; GET NUMBER BACK
	LD B,30H	; GO:  ASCII OFFSET
	SUB B		; SUBTRACT 
	CP 04		; IN RANGE?
	JR C GEND
	LD A,(0004)	; NO, DEFAULT
GEND:	LD (HSTDSC),A 	; SET UP 
	MCAL ZCRLF 	; TIDY 
;
;ASK FOR TRACK 
GTRK:	MCAL ZPRM 
TMS:    DEFM "Which Track (0 - 27hex) ? "
	DEFB 20H+80H 
TME:	LD DE,IBUFF	; PT. TO BUFFER
TGET:	MCAL ZGETLN	; GET I/P 
	LD DE,IBUFF
	LD HL,TME-TMS	; CALC. POSITN.
	ADD HL,DE
	EX DE,HL	; DE PT. TO DATA 
	INC DE		; TEST FOR 1 DIGIT
	LD A,(DE)
	CP 20H
	DEC DE 
	JR NZ,TG	; 2 DIGITS
	DEC DE		; ELSE STEP BACK
	LD A,30H
	LD (DE),A	; ZERO FILL
TG:	MCAL ZH2IN	; GET INTO A 
	CP 27H		; CHECK IT
	JR NC,GTRK	; ITS NOT OK
;	
GK1	LD (HSTTRK),A
	MCAL ZCRLF 
	RET 
;
CMND:	MCAL ZKEYIN	; WAIT FOR USER
	CP CR		; GO ON CR 
	RET Z 		
	CP ESC		; ESCAPE?
	JP Z,DONE 	; YES, GO HOME 
CEND:	RET		; RETURN OTHERS IN A
;
; CALCULATE SKEWED SECTOR AND ADVANCE TO IT:
;
NEXT:	LD HL,(SKEW)	; INDEX TO NEXT
	LD A,NSECS-1 	; DONE?
	CP L
	JR NZ,NX1	; CONTINUE
	LD HL,-1	; RESTART 
	LD A,(HSTTRK)	; GET TRACK
	CP 28H		; DONE 40 ?
	JR NZ,NX	; NO, CONTINUE
	LD A,-1		; ELSE RESET
NX:	INC A 
	LD (HSTTRK),A 
	MCAL ZFDRST	; RESET DISKS 
NX1:	INC HL		; ADVANCE
	LD (SKEW),HL
	LD DE,SK3TBL	; POINT TO TABL
	ADD HL,DE	; CALC. OFFSET
	LD A,(HL)	; GET SECT. NUMBER
	LD (HSTSEC),A	; SET IT UP
	RET 		; DONE 
;
SK3TBL:	DEFB 00,01,02,03
	DEFB 04,05,06,07
	DEFB 08,09
;
; DISPLAY STATUS:
STATUS:	MCAL ZPRM 
	DEFM "Reading Drive = "
	DEFB 20H+80H
	LD A,(HSTDSC)	; GET DRIVE 
	MCAL ZPRA	; PRINT 
	MCAL ZPRM 
	DEFM "  Track = "
	DEFB 20H+80H
	LD A,(HSTTRK)	; GET TRACK
	MCAL ZPRA 
	MCAL ZPRM 
	DEFM "H  Sector = "
	DEFB 20H+80H 
	LD A,(HSTSEC)	; GET SECTOR
	MCAL ZPRA
	MCAL ZPRM 
	DEFM "H  Sect. Count = "
	DEFB 20H+80H 	; GET SKEW 
	LD A,(SKEW)
	MCAL ZPRA
	MCAL ZCRLF	; TIDY UP 
	RET 
;
; DSCERR - CONVERT ERROR AND DISPLAY:
;
DSCERR:	LD A,(STATS)	; GET CODE
	DEC A
	JR Z,DATERR	; 1 - BAD DATA
	DEC A
	JR Z,WPERR	; 2 - WRITE PROTECT
	DEC A
	JR Z,SNF	; 3 - SECTOR NOT FOUND
	DEC A
	JR Z,NRDY	; 4 - DRIVE NOT READY
NODRV:	MCAL ZPRM	; ELSE NO DRIVE
	DEFM "No Drive."
	DEFB 0A0H
	JR ERRND
NRDY:	MCAL ZPRM 
	DEFM "Not Ready."
	DEFB 0A0H
	JR ERRND
DATERR:	MCAL ZPRM
	DEFM "Bad Data."
	DEFB 0A0H
	JR ERRND
WPERR:	MCAL ZPRM
	DEFM "Write Protected."
	DEFB 0A0H
	JR ERRND
SNF:	MCAL ZPRM
	DEFM "Sector Not Found."
	DEFB 0A0H
ERRND:  MCAL ZCRLF
	RET 
;
*INCLUDE DISK.GEN 
;
IBUFF:	DEFS	40H	; I/P BUFFER
	END 	DEFM "Sector No