
;CPM 2.2 BIOS 
	public	boot2
	public	const2,conin2,conout2,list2,auxout2,auxin2	
	public	home2,seldsk2,settrk2,setsec2,setdma2	
	public	read2,write2,listst2,sectrn2	
true	equ	-1
false	equ	not true

	maclib	z80


Banked22	equ	false
;Banked22	equ	true

nk$sys	equ	62		;system size in  kBytes
td	equ	nk$sys/10	;decimal tens digit
od	equ	nk$sys MOD 10	;decimal ones digit
td$asc	equ	td+30h		;ascci tens digit
od$asc	equ	od+30h		;ascii ones digit
k$byte	equ	1024		;bytes in a kilobyte
cpm$sz	equ	nk$sys*k$byte	;top system addres
v$20k	equ	20*k$byte	;twenty kByte 
cpm$bs	equ	cpm$sz-v$20k	;cpm bias value
ccp	equ	cpm$bs+3400h	;addres of ccp
bdos	equ	cpm$bs+3c00h	;addres of bdos
bios	equ	cpm$bs+4a00h	;addres of bios
;bios$r	equ	1000h-bios	;DDT offset load?
tpa	equ	100h		;addres of TPA
initIOB	equ	0ffh		;initial iobyte value

io$byte	equ	3		;address of iobyte
c$disk	equ	4		;address of current logged disk

;un-initialized data definition

;ui$data	equ	0fc00h		;3 256 blocks end feff
;ui$data	equ	eob		;3 256 blocks end of bios

df$drv	equ	0		;default drive
sec$sz	equ	80h		;sector size
fmt$sz	EQU	100h		;format buffer size
n$drvs	equ	4		;number of drives(1-4)

dsk$cmd equ 0D0h 
dsk$sts equ 0D0h 
dsk$drv		equ	0D1h ;drv
dsk$trkL	equ	0D2h ;trkLow
dsk$trkH	equ	0D3h ;trkHigh
dsk$secL	equ	0D4h ;secLow
dsk$secH	equ	0D5h ;secHigh
dsk$dmaL	equ	0D6h ;dmaLow
dsk$dmaH	equ	0D7h ;dmaHigh
dsk$sptL	equ	0D8h ;sptLow
dsk$sptH	equ	0D9h ;sptHigh
dsk$dmaB	equ	0dah ;Disk DMA Bank
dsk$order	equ	0dbh ;track order

cmd$read	equ	1
cmd$write	equ	2
cmd$log		equ	4
cmd$fmt		equ	8

;	org	bios

;bios jump vector table

boot2		jmp	init	;cold start
		jmp	warm	;warm start
const2	jmp	cns$ck	;get console status
conin2	jmp	cns$in	;console input
conout2
outCH:	jmp	cns$ot	;console output
list2		jmp	list	;printer output
auxout2	jmp	punch	;punch output
auxin2	jmp	reader	;reader input
home2		jmp	home	;home selected drive
seldsk2	jmp	seldsk	;select drive
settrk2	jmp	settrk	;set track
setsec2	jmp	setsec	;set sector
setdma2	jmp	setdma	;set tranfer address
read2		jmp	diskrd	;read disk
write2	jmp	diskwr	;write disk
listst2	jmp	listst	;getr printer status
sectrn2	jmp	sectrn	;translate sector
		jmp	format	;format a track

;bios variable storage

bt$cmd	db	0	;dcm command
bt$drv	db	0	;drive number
bt$trk	db	0	;track number
bt$sec	db	0	;sector number
bt$sp0	db	0	;spare
bt$sp1	db	0	;spare
bt$mod	db	0	;mode controls
bt$sts	db	0	;command status

bt$lad	dw	0	;load address
bt$lng	dw	0	;load length
bt$dma	dw	0	;system tranfer address

dt$ptr	dw	0	;drive table pointer
log$rq	db	0	;log on request

;log$buf	dw	0fb00h
log$buf	dw	dir$bf
log$dpb	equ	20h		;offset to dpb in buffer
log$ddf	equ	31h		;id sec - flags	

init:	
	mvi	a,0ffh
	out	dsk$dmab
	mvi	a,0
	out	0c0h	;set bank=0
warm:	
	ret

;disk executive

dsk$log
	lda	log$buf
	out	dsk$dmaL
	lda	log$buf+1	
	out	dsk$dmaH
	lda	bt$drv
	out	dsk$drv
	mvi	a,cmd$log
	out	dsk$cmd
	in	dsk$sts
	ana	a		;set ccr
	jnz	dsk$er		;exit error
	jr	dsk$ok		;normal exit

;disk executive

dsk$ex
	call	dpb$ad		;de points to dpb
	xchg			;hl ->dpb
	mov	a,m		;sptLow
	out	dsk$sptL
	inx	hl
	mov	a,m		;sptHigh
	out	dsk$sptH
	xra	a
	out	dsk$order	;sides
	lda	bt$dma
	out	dsk$dmaL
	lda	bt$dma+1	
	out	dsk$dmaH
	lda	bt$drv
	out	dsk$drv
	lda	bt$trk
	out	dsk$trkL
	lda	bt$sec
	out	dsk$secL
	lda	bt$cmd
	out	dsk$cmd
	in	dsk$sts
	ana	a		;set ccr
	ret

;read sector

diskrd:
	mvi	a,cmd$read
	sta	bt$cmd
	call	dsk$ex		;perform operation
	jnz	dsk$er		;exit error
	jr	dsk$ok		;normal exit

;write sector

diskwr:	
	mvi	a,cmd$write
	sta	bt$cmd
	call	dsk$ex		;perform operation
	jrz	dsk$ok		;normal exit if write ok
	jr	dsk$er		;exit error

;disk read write format exits and errors

dsk$ok:	
	xra	a		;clear a to indicate OK
	ret

dsk$er:	
	mvi	a,0FFh		;set a to indicate ERROR
	ret

format:	
	mvi	a,cmd$fmt
	sta	bt$cmd
	call	dsk$ex		;perform operation
	jrz	dsk$ok		;normal exit if write ok
	jr	dsk$er		;exit error

seldsk	lxi	h,0		;hl = zero if error
	mov	a,c		;put drive number in a
	sta	bt$drv		;store drive number
	cpi	n$drvs		;check if legal drive number
	rnc			;ret if illegal

	mov	a,e		;chk if need log on
	sta	log$rq		;save log on req in log$rq
	
retdsk	lda	bt$drv		;get drv number
	mov	l,a		;l=drive number
	mvi	h,0		;clear h
	dad	h		;*2
	dad	h		;*4
	dad	h		;*8
	dad	h		;*16
	lxi	d,d0$dph	;first dph
	dad	d		;hl=dph of drv number in c
	shld	dt$ptr		;store drive table pointer

;log on set dpb

log$on	lda	log$rq		;check log on req
	ani	01h		;log on bit test
	jrnz	dsk$ok		;already logged on

;read id sector

	call	dsk$log
	jrz	log$ck		;id sector got read
	lxi	h,0		;bad log on hl=0(no Drive table)
	jmp	dsk$er		;exit error

;check if a JADE disk


log$ck	
	lhld	log$buf		;get address of log buffer
	lxi	d,jadeid	;de points to id value
	mvi	b,id$sze	;label size
loop1	ldax	d		;get label character
	cmp	m		;match?
	jrnz	ck1440		;no - go chk for 1440
;	inx	h		;point to next chars
;	inx	d		;
	dcr	b		;dec count of characters
	jrnz	loop1		;again
	jr	yes$id

;check for pc1440 id (3$5 1440)

ck1440	lhld	log$buf	;hl points to sector(id) buffer
	lxi	d,id1440	;de points to id value
	mvi	b,id$sze	;label size
loop2	ldax	d		;get label character
	cmp	m		;match?
	jrnz	lg$type		;no - go chk drive type(no id)
	inx	h		;point to next chars
	inx	d		;
	dcr	b		;dec count of characters
	jrnz	loop2		;again


;diskette contains JADE id or 3$5 1440 id

yes$id	call	dpb$ad		;get dpb address in de
	lxi	b,log$dpb	;offset to dpb in buffer
	lhld	log$buf		;get address of buffer
	dad	b		;hl points to dpb in sector(id) buffer
	lxi	b,dpb$sz	;size of dpb
;	call	block		;move dpb on dd to bios dpb
	ldir
	lxi	d,log$ddf	;
	lhld	log$buf		;get address of dd
	dad	d		;hl points to dpb in sector(id) buffer
	mov	a,m		;get density flags on dd
	ani	04h		;test trk1 density
	cz	tr3740		;if single density use 3740
	cnz	trnone		;no sector translation
	lhld	dt$ptr		;reload ptr to dph table
	jmp	dsk$ok		;return with drv ptr in hl

; chk drive type - 0 or 1 can be 1440's 2 or 3 can be 3740's

lg$type	
;	ifz 	tSec-8		;if tSec is 8 assemble this else assume 1440
;	 lda	bt$drv		;3740 can be in 2 or 3
;	 ani	02h		;test if drive 2 0r 3
;	 jrnz	lg3740		;must be 2 or 3 
;	endif

;assume 1440

lg1440	call	trnone		;no translate 
	call	dpb$ad		;get dpb address in de
	lxi	b,dpb$sz	;size of dpb
	lxi	h,pc$pbk	;hl points to pc 1440 dpb
;	call	block		;move pc 1440 dpb  to bios dpb
	ldir
	lhld	dt$ptr		;reload ptr to dph table
	jmp	dsk$ok		;return with drv ptr in hl

;assume 3740

lg3740	call	tr3740		;translate for 3740
	call	dpb$ad		;get dpb address in de
	lxi	b,dpb$sz	;size of dpb
	lxi	h,sd$pbk	;hl points to single density dpb 3740
;	call	block		;move single dens dpb  to bios dpb
	ldir
	lhld	dt$ptr		;reload ptr to dph table
	jmp	dsk$ok		;return with drv ptr in hl

;set 3740 sector translation

tr3740	lxi	d,sdtran	;single density translation table
	lhld	dt$ptr		;ptr to dph table
	mov	m,e		;put xlat table pointer into dph at 0
	inx	h		;
	mov	m,d		;
	ret

;set no xlation

trnone	xra	a		;zero
	lhld	dt$ptr		;ptr to dph table
	mov	m,a		;put null xlat table pointer into dph at 0
	inx	h		;
	mov	m,a		;
	ret


;get drv par block address

dpb$ad	lhld	dt$ptr		;ptr to dph table
	lxi	d,10		;
	dad	d		;d points to dpb in dph
	mov	e,m		;get dpb from dph at offset 10
	inx	h		;
	mov	d,m		;
	ret


;home drive

home	mvi	c,0		;set track to 0 fall into settrk

;set track

settrk	mov	a,c		;track no in a from c
	sta	bt$trk		;store track number
	ret

;set sector

setsec	mov	a,c		;sector no in a from c
	sta	bt$sec		;store sector number
	ret

;set dma

setdma	mov	l,c		;just save in bt$dma
	mov	h,b
	shld	bt$dma
	ret

;sector translation

sectrn	mov	a,d		;testing tbl addr
	ora	e		;chk if 0
	jrz	notran		;no xlation
	xchg			;hl=xlat tbl
	dad	b		;hl + sec offset
	mov	l,m		;
	mvi	h,0		;assumed 8 bit sector numbers
	ret	
notran	lxi	h,1		;add one to sector number and ret
	dad	b		
	ret	

;define console io ports

cni$sp	equ	7dh
cni$sb	equ	02h
cni$si	equ	00h
cni$dp	equ	7ch

cno$sp	equ	7dh
cno$sb	equ	01h
cno$si	equ	00h
cno$dp	equ	7ch

io$rdy	equ	0FFh	;ready
asc$msk	equ	7Fh	;ascii mask

lf	equ	0ah
cr	equ	0dh
cntl$z	equ	1Ah

;console input status


cns$ck	in	cni$sp		;in status
	xri	cni$si		;adjust polarity
	ani	cni$sb		;mask status bit
	rz			;return zero if not ready
	mvi	a,io$rdy	;set ready
	ret			;return

;console input

cns$in	call	cns$ck		;check status
	jrz	cns$in		;repeat untill ready
	in	cni$dp		;in character
	ani	asc$msk		;mask to 7 bit ascii
	ret			;return

;console output

cns$ot	in	cno$sp		;in status
	xri	cno$si		;adjust polarity
	ani	cno$sb		;mask status bit
	jrz	cns$ot		;repeat untill ready
	mov	a,c		;get character in a
	ani	asc$msk		;mask to 7 bit ascii
	out	cno$dp		;out character
	ret			;return

;reader and punch

reader	mvi	a,cntl$z	;return eof
	ret			;return

punch	ret			;throw away

;printer

lst$dp	equ	7eH		;list data port
lst$st	equ	7fH		;list status port
lst$ctl	equ	lst$st		;control port
lst$msk	equ	00000001B	;status mask (ORPLY)
ctl$msk	equ	00000001b	;control mask (OSTB)
mem$msk	equ	00000010b	;sbc mem mask 10=out 00=in

listst	in	lst$st		;
	ani	lst$msk		;
	rz			;not ready
	mvi	a,0ffh		;ready
	ret
	
list	call	listst		;get status
	jrz	list		;wait for ready
	mov	a,c		;get char from c
	out	lst$dp		;out char to data port
	mvi	a,ctl$msk		;strobe data
	out	lst$ctl		;strobe
	ret			;return

;display string

msg$ot	push	psw		;save ccr and a
loop3	mov	c,m		;get char fron where hl points
	call	outCH		;output char
	mov	a,m		;get char again to test sign
	inx	hl		;inc to next char
	ani	80h		;test sign bit
	jrz	loop3		;repeat until sign bit set
	pop	psw		;restore ccr and a
	ret			;;return

block	mov	a,m		;
	stax	d		;
	inx	h		;
	inx	d		;
	dcx	b		;
	mov	a,b		;
	ora	c		;
	jnz	block		;
	ret			;


;3740 parameters

sdtran:	db	01h,07h,0dh,13h,19h,05h
		db	0bh,11h,17h,03h,09h,0fh
		db	15h,02h,08h,0eh,14h,1ah
		db	06h,0ch,12h,18h,04h,0ah
		db	10h,16h

;default drive parametr block for 3$5" pc1440
;		pc1440
;		IBM PC
pc$pbk:	dw	72		;spt
	db	4		;bsh
	db	15		;blm
	db	0		;exm
	dw	710		;dsm
	dw	255		;drm
	db	0f0h		;al0
	db	0		;al1
	dw	64		;cks
	dw	2		;off

;default drive parametr block for 8" IBM3740

sd$pbk:	dw	26		;spt
	db	3		;bsh
	db	7		;blm
	db	0		;exm
	dw	242		;dsm
	dw	63		;drm
	db	0c0h		;al0
	db	0		;al1
	dw	16		;cks
	dw	2		;off

;messages

msg$le:	db	cr,lf,'LOAD ERRO'
		db	52h+80h

;id label

id1440:	db	'3.5 1440'

jadeid:	db	'Jade ID ' ;"JADE ID" ?????
id$sze:	equ	$-jadeid

;drive parameter area

d0$dph:	dw	0		;xlat table
	dw	0		;scratch area
	dw	0		;scratch area
	dw	0		;scratch area
	dw	dir$bf		;directory buffer
	dw	d0$dpb		;drive parameter block
	dw	d0$chk		;chk for disk change area
	dw	d0$all		;drive allocation table
d1$dph:	dw	0
	dw	0
	dw	0
	dw	0
	dw	dir$bf
	dw	d1$dpb
	dw	d1$chk
	dw	d1$all
d2$dph:	dw	0
	dw	0
	dw	0
	dw	0
	dw	dir$bf
	dw	d2$dpb
	dw	d2$chk
	dw	d2$all
d3$dph:	dw	0
	dw	0
	dw	0
	dw	0
	dw	dir$bf
	dw	d3$dpb
	dw	d3$chk
	dw	d3$all

eob:	

;Un-initialized data area

;reserve drive parameter block DPB's

dpb$sz	equ	15	;size of drive parameter block

d0$dpb	ds	dpb$sz	;reserve 15 byte for drive 0
d1$dpb	ds	dpb$sz	;reserve 15 byte for drive 1
d2$dpb	ds	dpb$sz	;reserve 15 byte for drive 2
d3$dpb	ds	dpb$sz	;reserve 15 byte for drive 3

; drive allocation area

all$sz equ	91

d0$all	ds	all$sz
d1$all	ds	all$sz
d2$all	ds	all$sz
d3$all	ds	all$sz

;changed disk area

chk$sz	equ	64

d0$chk	ds	chk$sz
d1$chk	ds	chk$sz
d2$chk	ds	chk$sz
d3$chk	ds	chk$sz


dir$bf	ds	80h

