	TITLE	'BIOSHSEL NONBANKED 5 MB WINCHESTER 4K / 16 K'
;
;
;******************************************************************
;
;
;	BIOSZ80
;
;	I/O Drivers for CP/M 2.2 64 K CPU V (Z80A)
;	THREE DRIVE DOUBLE DENSITY DOUBLE SIDE 48 OR 96 TPI
;	ONE DRIVE 8" SINGLE SIDE SINGLE DENSITY
;	TWO DRIVE HARDDISK 5MB
;
;	VERSION 5.3	14.08.83  /  MR / AN
;
;
;
;
	MACLIB	Z80		;USE ENHANCED Z80 OPCODES
;
;
;
TRUE	EQU	0FFFFH		;VALUE OF "TRUE"
FALSE	EQU	NOT TRUE	;"FALSE"
;
;
BIO96	EQU	TRUE
;
;
CLUST4	EQU	FALSE		;CLUSTERGROESSE 4K
;
;
;
;	CONSTANTS FOR MINIFLOPPY 5"
;
;
;
OFFSET	EQU	4		; SEKTOR USED FOR LOADER AND CP/M
HSTSIZ	EQU	1024		; LOGICAL SECTORSIZE
HSTSPT	EQU	4		; LOGICAL SECTORS PER TRACK
HSTDSE	EQU	2		; MULTIPLY LOGICAL TO PHYSICAL SECTOR
LSC	EQU	32		; 128 BYTE SECTOR PER TRACK
	IF	NOT BIO96
DKS	EQU	256		; BLOCKS PER DISK
MAXTRA	EQU	35		; MAX. SPUREN
	ENDIF
	IF	BIO96
DKS	EQU	272		; BLOCKS PER DISK
MAXTRA	EQU	70		; MAX.SPUREN
	ENDIF
SKF	EQU	0		; NO SECTOR SKEW
DEBLOCK	EQU	TRUE
;
;--------------------------------------------------------------------
;
;	MOS MONITOR EQUATES
;
DENTRY	EQU	0FEA1H		; FLOPPY IO-DENTRY
ŠSENTRY	EQU	0FEA4H		; FLOPPY IO-SENTRY
; 
WINCH	EQU	0FE91H	; PLATTENTREIBER-EINGANG DENTRY
SWINCH	EQU	0FE94H	; PLATTENTREIBER-EINGANG SENTRY
;
CIY	EQU	0FE03H		; EINGABE TASTATUR
CSTY	EQU	0FE12H		; STATUS TASTATUR
DISPY	EQU	0FE09H		; ZEICHEN AUF BILDSCHIRM
LOY	EQU	0FE0FH		; ZEICHEN AUF DRUCKER
LSTY	EQU	0FED0H		; DRUCKERSTATUS
COMBIN	EQU	0FE06H		; COMBO INPUT
SIOAIN	EQU	0FEBBH		; SIO A INPUT
SIOAOU	EQU	0FEBEH		; SIO A OUTPUT
SIOBIN	EQU	0FEC1H		; SIO B INPUT
SIOBOU	EQU	0FEC4H		; SIO B OUTPUT
SIOAST	EQU	0FECAH		; SIO A STATUS ZEICHEN BEREIT
SIOBST	EQU	0FECDH		; SIO B STATUS ZEICHEN BEREIT
PIO	EQU	0FEC7H		; PIO CENTRONICS OUTPUT
PIOST	EQU	0FED3H		; PIO STATUS DRUCKER
SIOST	EQU	0FED6H		; SIO STATUS DRUCKER
;
;
FLOPOS	EQU	84H	; POSITION TO FLOPPY
SELECT	EQU	1	; SELECT DRIVE
READF	EQU	82H	; READ FUNCTION SECTORWISE
WRITF	EQU	83H	; WRITE FUNCTION SECTORWISE
RECAL	EQU	0AH	; RECALIBRATE DRIVE
PLAPOS	EQU	8AH	; POSITION PLATTE
READP	EQU	88H	; LESEN PLATTE
WRITP	EQU	89H	; SCHREIBEN PLATTE
CR	EQU	0DH	; CARRIAGE RETURN
LF	EQU	0AH	; LINE FEED
WKZEL	EQU	0FFFFH	; ZELLE WARM/KALTSTART
;
;
;
VERS	EQU	22		;VERSION 2.2
VSKS	EQU	53		;SKS VERSION - NUMBER
;
BASE	EQU	0h		;beginning of addressable RAM
START	EQU	BASE
EBDOS	EQU	BASE+5
IOBYTE	EQU	BASE+3
CDISK	EQU	BASE+4
BUFF	EQU	BASE+128
;
	IF	NOT CLUST4
BIAS	EQU	0C000H		; BASE OF CCP
	ENDIF
	IF	CLUST4
BIAS	EQU	0BC00H
	ENDIF
CPMLEN	EQU	2000H
patch	equ	1600h+bias
;
cpmb	equ	patch-1600h		;base of cpm console processor
bdos	equ	cpmb+806h	;basic dos (resident portion)
cpml	equ	patch-cpmb		;length (in bytes) of cpm system
;
;
NRDISK	EQU	06		;six disks supported
;
retry	equ	10		;max retries on disk i/o before error
;
;
	ORG	PATCH
;
;
;
;	perform following functions
;	boot	cold start
;	wboot	warm start (save i/o byte)
;	const	console status
;		reg-a = 00 if no character ready
;		reg-a = ff if character ready
;	conin	console character in (result in reg-a)
;	conout	console character out (char in reg-c)
;	list	list out (char in reg-c)
;	punch	punch out (char in reg-c) 
;	reader	paper tape reader in (result to rEg-a) 
;	home	move to track 00
;
;	(the following calls set-up the io parameter block for the
;	mos, which is used to perform subsequent reads and writes)
;	seldsk	select disk given by reg-c (0,1,2...)
;	settrk	set track address (0,...76) for subsequent read/write
;	setsec	set sector address (1,...,26) for subsequent read/write
;	setdma	set subsequent dma address (initially 80h)
;
Š;	(read and write assume previous calls to set up the io parameters)
;	read	read track/sector to preset dma address
;	write	write track/sector from preset dma address
;
;
;	jump vectors for indiviual routines
;
;
;
	JMP	KBOOT
WBOOTE:	jmp	wboot
	jmp	const
	JMP	conin
	jmp	conout
	jmp	list
	jmp	punch
	jmp	reader
	jmp	home
	jmp	seldsk
	jmp	settrk
	jmp	setsec
	jmp	setdma
	JMP	READ1
	JMP	WRITE1
	JMP	listst
	JMP	SECTR1
;
;
;	IO BYTE ROUTINEN
;
;
CONST:	LDA	IOBYTE
	CALL	INDEX
	DW	SIOBST
	DW	CSTY
	DW	RDRST
	DW	CSTY
;
RDRST:	LDA	IOBYTE
	RRC
	CALL	INDEX1
	DW	SIOBST
	DW	SIOAST
	DW	BUSY
	DW	BUSY
;
BUSY:	MVI	A,0		;IMMER NICHT BEREIT
	RET
;
CONIN:	LDA	IOBYTE
	CALL	INDEX
	DW	SIOAIN
	DW	CIY
	DW	READER
	DW	CIY
;
CONOUT:	LDA	IOBYTE
	CALL	INDEX
	DW	SIOAOU
	DW	DISPY
	DW	LIST
	DW	DISPY
;
LISTST:	LDA	IOBYTE
	RLC
	RLC			;SHIFT INTO POSITION
	CALL	INDEX
	DW	PIOST
	DW	CSTY
	DW	LSTY
	DW	SIOST
;
LIST:	LDA	IOBYTE
	RLC
	RLC
	CALL	INDEX
	DW	PIOPRN
	DW	DISPY
	DW	LOY
	DW	SIOAOU
;
PUNCH:	LDA	IOBYTE
	RRC
	RRC
	RRC
	CALL	INDEX1
	DW	SIOBOU
	DW	SIOAOU
	DW	LOY
	DW	LOY
;
READER:	LDA	IOBYTE
	RRC
	CALL	INDEX1
	DW	SIOBIN
	DW	SIOAIN
	DW	COMBIN
	DW	COMBIN
;
INDEX:	RLC
INDEX1:	ANI	6		;MASK OTHER BITS
	XTHL			;RETTE HL HOLE TABELLE
	PUSH	D
	MOV	E,A
	MVI	D,0
	DAD	D		;+OFFSET
	MOV	A,M		;HOLE LSB
	INX	H
	MOV	H,M		;HOLE MSB
	MOV	L,A		;ADRESSE IN HL
	POP	D
	XTHL
	RET
;
;
PIOPRN:	CALL	PIOST
	MOV	A,B
	ANI	4		;CHECK FAULT ERROR
	JNZ	PIO		;NO ERROR THEN PRINT
	LXI	H,PIOMSG	;PRINT ERROR MESSAGE
	PUSH	B
	CALL	TXCO
	POP	B
	JMP	PIO
;
;
PIOMSG:	DB	7,7,7,7,7,7,7,7,7,7,0
;
;
	MACLIB	DISKDEF	; LOAD THE DISK DEFINATION LIBRARY
	DISKS	NRDISK
;
	IF	NOT BIO96
	DISKDEF	0,1,LSC,SKF,1024,DKS,64,64,OFFSET
	ENDIF
	IF	BIO96
	DISKDEF	0,1,LSC,SKF,2048,DKS,128,128,OFFSET
	ENDIF
	DISKDEF	1,0
	DISKDEF	2,0
	DISKDEF	3,1,26,6,1024,240,64,64,2

	IF	NOT CLUST4
	DISKDEF	4,1,128,0,16384,304,512,0,2
	DISKDEF	5,4
	ENDIF
	IF	CLUST4
	DISKDEF	4,1,128,0,4096,1216,1280,0,2
	DISKDEF	5,4
	ENDIF
;
;
;
IOINIT:	MVI	A,0		;DEFAULT DRIVE 0
	STA	CDISK
	MVI	A,95H		;DEFAULT IOBYTE
	STA	IOBYTE
	RET
;
;
txco:	mov	a,m
	ora	a
	rz
	mov	c,a
	call	dispy
	inx	h
	jr	txco
;
;
;*********************************************************
;*
;*	uninitialized ram data areas
Š;*
;*********************************************************
;
;
;
beacpm	equ	$
;
hstdsk:	db	0		; host disk number
hsttrk:	db	0,0		; host track number
hstsec:	db	0		; host sector number
;
sekhst:	db	0		; seek shr secshf
hstact:	db	0		; host active flag
hstwrt:	db	0		; host written flag
;
unacnt:	db	0		; unalloc rec cnt
unadsk:	db	0		; last unalloc disk
unatrk:	db	0,0		; last unalloc track
unasec:	db	0		; last unalloc sector
;
;************************************************************
;
;
;*************************************************************
;
sekdsk:	db	0		; seek disk number
sektrk:	db	0,0		; seek track number
seksec:	db	0		; seek sector number
;
;*********************************************************************
;
erflag:	db	0		; error reporting
rsflag:	db	0		; read sector flag
readop:	db	0		; 1 if read operation
wrtype:	db	0		; write operation type
dmaadr:	dw	buff		; last dma address
spa:	ds	2		; stack-pointer
;
;
	page
	IF	DEBLOCK
;
;*****************************************************
;*						     *
;*	sector deblocking algorithms for cp/m 2.2    *
;*						     *
;*****************************************************
;
;
;	utility macro to compute sektor mask
smask	macro	hblk
;;	compute log2(hblk), return @x as result
;;	(2 ** @x = hblk on return)
@y	set	hblk
@x	set	0
;;	count right shifts of @y until = 1
	rept	8
	if	@y = 1
	exitm
	endif
;;	@y is not 1, shift right one position
Š@y	set	@y shr 1
@x	set	@x + 1
	endm
	endm
;
;*****************************************************
;*                                                   *
;*	   CP/M to host disk constants 	             *
;*                                                   *
;*****************************************************
blksiz	equ	1024		;CP/M allocation size
hstblk	equ	hstsiz/128	;CP/M sects/host buff
cpmspt	equ	hstblk * hstspt	;CP/M sectors/track
secmsk	equ	hstblk-1	;sector mask
	smask	hstblk		;compute sector mask
secshf	equ	@x		;log2(hstblk)
;
	PAGE
;*****************************************************
;*                                                   *
;*        BDOS constants on entry to write           *
;*                                                   *
;*****************************************************
wrall	equ	0		;write to allocated
wrdir	equ	1		;write to directory
wrual	equ	2		;write to unallocated
;
;
;*****************************************************
;*                                                   *
;*	The READ entry point takes the place of      *
;*	the previous BIOS defintion for READ.        *
;*                                                   *
;*****************************************************
read:
	;read the selected CP/M sector
	xra	a
	sta	unacnt
	mvi	a,1
	sta	readop		;read operation
	sta	rsflag		;must read data
	mvi	a,wrual
	sta	wrtype		;treat as unalloc
	jmp	rwoper		;to perform the read
;
;*****************************************************
;*                                                   *
;*	The WRITE entry point takes the place of     *
;*	the previous BIOS defintion for WRITE.       *
;*                                                   *
;*****************************************************
write:
	;write the selected CP/M sector
	xra	a		;0 to accumulator
	sta	readop		;not a read operation
	mov	a,c		;write type in c
	sta	wrtype
	cpi	wrual		;write unallocated?
	jrnz	chkuna		;check for unalloc
;
;	write to unallocated, set parameters
Š	mvi	a,blksiz/128	;next unalloc recs
	sta	unacnt
	lda	sekdsk		;disk to seek
	sta	unadsk		;unadsk = sekdsk
	lhld	sektrk
	shld	unatrk		;unatrk = sectrk
	lda	seksec
	sta	unasec		;unasec = seksec
;
chkuna:
	;check for write to unallocated sector
	lda	unacnt		;any unalloc remain?
	ora	a
	jrz	alloc		;skip if not
;
;	more unallocated records remain
	dcr	a		;unacnt = unacnt-1
	sta	unacnt
	lda	sekdsk		;same disk?
	lxi	h,unadsk
	cmp	m		;sekdsk = unadsk?
	jrnz	alloc		;skip if not
;
;	disks are the same
	lxi	h,unatrk
	call	sektrkcmp	;sektrk = unatrk?
	jrnz	alloc		;skip if not
;
;	tracks are the same
	lda	seksec		;same sector?
	lxi	h,unasec
	cmp	m		;seksec = unasec?
	jrnz	alloc		;skip if not
;
;	match, move to next sector for future ref
	inr	m		;unasec = unasec+1
	mov	a,m		;end of track?
	cpi	cpmspt		;count CP/M sectors
	jrc	noovf		;skip if no overflow
;
;	overflow to next track
	mvi	m,0		;unasec = 0
	lhld	unatrk
	inx	h
	shld	unatrk		;unatrk = unatrk+1
;
noovf:
	;match found, mark as unnecessary read
	xra	a		;0 to accumulator
	sta	rsflag		;rsflag = 0
	jr	rwoper		;to perform the write
;
alloc:
	;not an unallocated record, requires pre-read
	xra	a		;0 to accum
	sta	unacnt		;unacnt = 0
	inr	a		;1 to accum
	sta	rsflag		;rsflag = 1
;
;*****************************************************
;*                                                   *
Š;*	Common code for READ and WRITE follows       *
;*                                                   *
;*****************************************************
rwoper:
	;enter here to perform the read/write
	xra	a		;zero to accum
	sta	erflag		;no errors (yet)
	lda	seksec		;compute host sector
	rept	secshf
	ora	a		;carry = 0
	rar			;shift right
	endm
	sta	sekhst		;host sector to seek
;
;	active host sector?
	lxi	h,hstact	;host active flag
	mov	a,m
	mvi	m,1		;always becomes 1
	ora	a		;was it already?
	jrz	filhst		;fill host if not
;
;	host buffer active, same as seek buffer?
	lda	sekdsk
	lxi	h,hstdsk	;same disk?
	cmp	m		;sekdsk = hstdsk?
	jrnz	nomatch
;
;	same disk, same track?
	lxi	h,hsttrk
	call	sektrkcmp	;sektrk = hsttrk?
	jrnz	nomatch
;
;	same disk, same track, same buffer?
	lda	sekhst
	lxi	h,hstsec	;sekhst = hstsec?
	cmp	m
	jrz	match		;skip if match
;
nomatch:
	;proper disk, but not correct sector
	lda	hstwrt		;host written?
	ora	a
	cnz	writehst	;clear host buff
;
filhst:
	;may have to fill the host buffer
	lda	sekdsk
	sta	hstdsk
	lhld	sektrk
	shld	hsttrk
	lda	sekhst
	sta	hstsec
	lda	rsflag		;need to read?
	ora	a
	cnz	readhst		;yes, if 1
	xra	a		;0 to accum
	sta	hstwrt		;no pending write
;
match:
	;copy data to or from buffer
	lda	seksec		;mask buffer number
Š	ani	secmsk		;least signif bits
	mov	l,a		;ready to shift
	mvi	h,0		;double count
	rept	7		;shift left 7
	dad	h
	endm
;	hl has relative host buffer address
	lxi	d,hstbuf
	dad	d		;hl = host address
	xchg			;now in DE
	lhld	dmaadr		;get/put CP/M data
	mvi	c,128		;length of move
	lda	readop		;which way?
	ora	a
	jrnz	rwmove		;skip if read
;
;	write operation, mark and switch direction
	mvi	a,1
	sta	hstwrt		;hstwrt = 1
	xchg			;source/dest swap
;
rwmove:
	;C initially 128, DE is source, HL is dest
	ldax	d		;source character
	inx	d
	mov	m,a		;to dest
	inx	h
	dcr	c		;loop 128 times
	jrnz	rwmove
;
;	data has been moved to/from host buffer
	lda	wrtype		;write type
	cpi	wrdir		;to directory?
	lda	erflag		;in case of errors
	rnz			;no further processing
;
;	clear host buffer for directory write
	ora	a		;errors?
	rnz			;skip if so
	xra	a		;0 to accum
	sta	hstwrt		;buffer written
	call	writehst
	lda	erflag
	ret
;
;*****************************************************
;*                                                   *
;*	Utility subroutine for 16-bit compare        *
;*                                                   *
;*****************************************************
sektrkcmp:
	;HL = .unatrk or .hsttrk, compare with sektrk
	xchg
	lxi	h,sektrk
	ldax	d		;low byte compare
	cmp	m		;same?
	rnz			;return if not
;	low bytes equal, test high 1s
	inx	d
	inx	h
	ldax	d
Š	cmp	m	;sets flags
	ret
;
	ENDIF
;
	PAGE
;*****************************************************
;*                                                   *
;*	WRITEHST performs the physical write to      *
;*	the host disk, READHST reads the physical    *
;*	disk.					     *
;*                                                   *
;*****************************************************
writehst:
	;hstdsk = host disk #, hsttrk = host track #,
	;hstsec = host sect #. write "hstsiz" bytes
	;from hstbuf and return error flag in erflag.
	;return erflag non-zero if error
	mvi	a,writf
	jmp	iofun
;
readhst:
	;hstdsk = host disk #, hsttrk = host track #,
	;hstsec = host sect #. read "hstsiz" bytes
	;into hstbuf and return error flag in erflag.
	mvi	a,readf
	jmp	iofun
;
;
SELDSK:	;SELECT DISK GIVEN BY REGISTER C
	MVI	H,00H		;RETURN 0000 IF ERROR
	MOV	L,H
	MOV	A,C
	CPI	NRDISK+5	;TOO LARGE?
	RNC			;LEAVE HL = 0000
	CPI	9
	JNC	SELD0
	CPI	4
	RNC
;
SELD0:	STA	SEKDSK	; DRIVE NUMBER
	JC	SELD1
	SUI	5
	MOV	C,A
	PUSH	B
	MVI	A,4
	NOP
	NOP
	NOP
;	CALL	DENTRY
	POP	B
SELD01:	MVI	A,80H
	JMP	SELD2
SELD1:	PUSH	B
	PUSH	H
	MVI	A,4
	CALL	WINCH
	POP	H
	POP	B
SELD11:	MVI	A,20H
SELD2:	STA	WRITE+74
	MOV	L,C		;HL=DISK NUMBER
	DAD	H		;*2
	DAD	H		;*4
	DAD	H		;*8
	DAD	H		;*16
	LXI	D,DPBASE
	DAD	D		;HL=DISK HEADER TABLE ADDRESS
	RET
;
;
;
;
READ1:	CALL	DEBSTA
	JC	READ	; DEBLOCK 5DD
	MVI	A,READF
	JMP	STAHST	; STANDARD 8SD
;
WRITE1:	CALL	DEBSTA
	JC	WRITE	; DEBLOCK 5DD
	MVI	A,WRITF	
	JMP	STAHST	; STANDARD 8SD
;
SECTR1:	CALL	DEBSTA
	JC	SECTRA
	MVI	B,0
Š	XCHG
	DAD	B
	MOV	L,M
	MVI	H,0
	RET
;
;
;
DEBSTA:	LDA	SEKDSK
	CPI	3
	RC
	CPI	9
	CMC
	RET
;
HOME:			; MOVE TO HOME POSITION
	LDA	HSTWRT
	ORA	A
	JrNZ	HOMED
	STA	HSTACT
HOMED:;			  TREAT AS TRACK 00 SEEK
	LXI	B,0
;
SETTRK:	;SET TRACK ADDRESS GIVEN BY C
	SBCD	SEKTRK
	RET
;
SETSEC:	;SET SECTOR NUMBER GIVEN BY C
	LXI	H,SEKSEC
	MOV	M,C
	RET
;
SETDMA:	;SET DMA ADDRESS GIVEN BY REGS B,C
	SBCD	DMAADR
	RET
;
;
SECTRA:	;SECTOR TRANSLATE SUBROUTINE
	MOV	H,B
	MOV	L,C
	RET
;
IOFUN:	MVI	C,RETRY
	MVI	H,0
	MOV	L,H
Š	DAD	SP
	SHLD	SPA
	LXI	SP,STP
IOFUN1:	PUSH	B
	PUSH	PSW
	LDA	HSTDSK
	CPI	3
	JNC	IOFUNP
;
	MVI	L,0
	LDA	HSTTRK
	MOV	E,A
IOF1:	CPI	MAXTRA			; MAX TRACK?
	JRC	IOFUN2
IOF2:	SUI	MAXTRA
	MOV	E,A
	MVI	L,1
IOFUN2:	LDA	HSTDSK
	ADD	A
	ADD	A
	ADD	A
	ADD	A
	ORA	L
	MOV	L,A
	LDA	HSTSEC
Š	REPT	HSTDSE
	ADD	A
	ENDM
	INR	A
	MOV	D,A
	MVI	A,FLOPOS
	CALL	SENTRY
	JRC	IOFUNE
	IF	DEBLOCK		; DEBLOCKING
	LXI	B,HSTBUF
	ENDIF
	LXI	D,HSTSIZ
IOFUNK:	POP	PSW
	PUSH	PSW
	CALL	DENTRY
	MVI	A,0
	JRNC	IOFUN5
IOFUNE:	POP	D		; ERROR
	MOV	A,C
	POP	B
	ANI	80H
	JRZ	IOFE5
	DCR	C
	MOV	A,D
	JRNZ	IOFUN1
IOFE5:	MVI	A,1
IOFUN5:	STA	ERFLAG
	lhld	spa
	sphl
	ret
;
;
STAHST:
	MVI	C,RETRY
	MVI	H,0
	MOV	L,H
	DAD	SP
	SHLD	SPA
	LXI	SP,STP
IO8ZO:	PUSH	B
	PUSH	PSW
	MVI	L,30H		;8" FLOPPY
	LDA	SEKTRK
	MOV	E,A
	LDA	SEKSEC
	MOV	D,A
	MVI	A,FLOPOS
	CALL	SENTRY
	JRC	IOFU81
	LHLD	DMAADR
	MOV	B,H
	MOV	C,L
	LXI	D,80H
	POP	PSW
	PUSH	PSW
	CALL	DENTRY
	MVI	A,0
	JRNC	IOFUN5
IOFU81:	POP	D
	MOV	A,C
	POP	B
	ANI	80H
	JRZ	IOFE5
	DCR	C
	MOV	A,D
	JRNZ	IO8ZO
	JR	IOFE5
;
;
IOFUNP:	
	POP	PSW
	ADI	6
	PUSH	PSW
	LDA	HSTSEC
	ADD	A
	ADD	A
	INR	A
	MOV	C,A
	LHLD	HSTTRK
	MOV	A,H
	RAR
	MOV	H,A
Š	MOV	A,L
	RAR
	MOV	L,A
	MOV	A,C
	JRNC	IOFP1
	ADI	64
IOFP1:	MOV	C,A
	MVI	B,0
	MOV	A,H
	RAR
	MOV	H,A
	MOV	A,L
	RAR
	MOV	L,A
	LXI	D,76
	JRC	IOFP2
	DAD	D
	JR	IOFP3
IOFP2:	XCHG
	MOV	A,L
	SUB	E
	MOV	L,A
	MOV	A,H
	SBB	D
	MOV	H,A
IOFP3:	XCHG
	LDA	HSTDSK
	SUI	9
	ADD	A
	ADD	A
	ADD	A
	ADD	A
	MOV	L,A
Š	MVI	A,PLAPOS
	CALL	SWINCH
	LXI	B,HSTBUF
	LXI	D,HSTSIZ
	POP	PSW
	PUSH	PSW
	CALL	WINCH
	MVI	A,0
	JNC	IOFUN5
	POP	D
	MOV	A,C
	POP	B
	ANI	10H
	JRZ	IOFU5
	PUSH	B
	PUSH	D
	MVI	A,0AH
	CALL	WINCH
	POP	D
	POP	B
IOFU5:	MOV	A,D
	SUI	6
	DCR	C
	JNZ	IOFUN1
	JMP	IOFE5
;
;
;
BOOTF:	DB	'BOOTSTRAP-ERROR',CR,LF
	db	0
;
;
WBOOTF:	LXI	H,BOOTF
	CALL	TXCO
	jr	WBOOTG
;
;
;
;******************************************
;*  COLD START LOADER                     *
;******************************************
;
;
;
;
;
KBOOT:
;	read cp/m from disk - assuming there is a 128 byte cold start
;
	lxi	h,signon
	call	txco
	CALL	IOINIT
	MVI	A,1
	jr	WBOOTG
;
WBOOT:	MVI	A,0
WBOOTG:	STA	WKZEL
	LXI	SP,STP
	MVI	A,FLOPOS
	MVI	L,0		;DRIVE 0
	MVI	E,1		;TRACK
	MVI	D,0BH		;SECTOR
	CALL	SENTRY
	jrc	WBOOTF
	LXI	B,CPMB
	LXI	D,CPML
	MVI	A,READF
	CALL	DENTRY
	JRC	WBOOTF
;
;
CPMET1	EQU	$
;---------------------------------------------------------------------
CPMAT2	EQU	$
;
;
	LDA	CDISK
	ANI	0FH
	CPI	0BH
	CNC	IOINIT
	CPI	9
	JNC	WLOAD
	CPI	NRDISK-2
	CNC	IOINIT
;
;
;
WLOAD:	LXI	H,START
	MVI	B,0C3H
	MOV	M,B
	LXI	D,WBOOTE
	INX	H
	MOV	M,E
	INX	H
	MOV	M,D
	LXI	H,EBDOS
	MOV	M,B
	LXI	D,BDOS
	INX	H
	MOV	M,E
	INX	H
	MOV	M,D
;
;
;
;
	LDA	CDISK
	MOV	C,A
	LDA	WKZEL
	ORA	A
	JNZ	CPMB
	JMP	CPMB+3
;
;
SIGNON:	DB	0CH,1BH,11H
	DB	'CP/M '
	DB	VERS/10+'0','.',VERS MOD 10+'0',' - '
	DB	VSKS/10+'0','.',VSKS MOD 10+'0','  '
	DB	'DT                 '
	DB	CR,CR,LF
	DB	0
;
;
;
;
CPMEND	EQU	$
;
;*********************************************************************;
;
	ORG	CPMAT2
;
	DS	128		; INTERNAL STACK
STP	EQU	$		
;
;
; floppy ram
;
DIRBUF:	DS	80H		; BUFFER IN MOS-AREA

ALV0:	DS	ALS0		; DRIVE 0, SIDE 0+1 = A
CSV0:	DS	CSS0
ALV1:	DS	ALS1		; DRIVE 1, SIDE 0+1 = B
CSV1:	DS	CSS1
ALV2:	DS	ALS2		; DRIVE 2, SIDE 0+1 = C
CSV2:	DS	CSS2
ALV3:	DS	ALS3
CSV3:	DS	CSS3
ALV4:	DS	ALS4		; DRIVE 0 HARDDISK = J
CSV4:	DS	CSS4
ALV5:	DS	ALS5		; DRIVE 1 HARDDISK = K
CSV5:	DS	CSS5
;
;
;
hstbuf:	ds	HSTSIZ		; host buffer
;
;
;--------------------------------------------------------------------
	ORG	0FF9CH
;
	DW	CPMB
	DS	1
	DW	CPMLEN
	DS	3
	MVI	A,0C9H
	STA	0E100H
	DS	1
	DW	PATCH
;
;
	ORG	0FE92H
	DW	0E100H
	DS	1
	DW	0E105H
;
;
	END
