
;CPM 2.2 BIOS 

true	equ	-1
false	equ	not true

AS8080 equ	true

	ift AS8080
	z80
	else
	maclib	z80
	endif
	


;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	;for regular 62k with 4 PC1440 drives	
ui$data	equ	0fA00h	;for 4 PC1440, 2 IBM3740, 2 4MB Hard drives
;ui$data	equ	eob	

; memory map for bios,xbios and unintialized data areas
;   					for 62 k system
;	bios		bios+1k	F200-F5FF
;	xbios 	xbios+1k	F600-F9FF
;	uidata			FA00-FEFF
;	uidata	EndOfMemory-256 (for interrupt vectors)

df$drv	equ	0		;default drive
sec$sz	equ	80h		;sector size
n$drvs	equ	6		;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

	jmp	init	;cold start
	jmp	warm	;warm start - reload ccp + bdos
	jmp	cns$ck	;get console status
	jmp	cns$in	;console input
outCH:	jmp	cns$ot	;console output
	jmp	list	;printer output
	jmp	punch	;punch output
	jmp	reader	;reader input
	jmp	home	;home selected drive
	jmp	seldsk	;select drive
	jmp	settrk	;set track
	jmp	setsec	;set sector
	jmp	setdma	;set tranfer address
	jmp	diskrd	;read disk
	jmp	diskwr	;write disk
	jmp	listst	;getr printer status
	jmp	sectrn	;translate sector

;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	eoui
log$dpb	equ	20h		;offset to dpb in buffer
log$ddf	equ	31h		;id sec - flags	

;init stuff is overlayed by directory buffer

dir$bf	equ	$

;get system size in ascii

init	lxi	sp,0080h	;set initial stack

c$logo	lxi	h,msg$so	;sign on message
	call	msg$ot		;out message
	lhld	bios+4		;get warm address
	shld	bios+1		;make cold point to warm

	if 	Banked22
	 mvi	a,1		;bank	1
	 out	0c0h		;emu bank select
	endif

	xra	a		;clear accumulator
	sta	io$byte		;store at iobyte
	sta	c$disk		;current logged disk =0

	if 	Banked22
	 xra	a		;bank	0
	 out	0c0h		;emu bank select

	 mvi	e,0	;1	; log on request
	 mvi	c,0		;drive 0
	 call	seldsk		;select drive
	 lxi	b,8000h	;cpm ccp address in bank 0
	 call	setdma		;set dma
	 mvi	c,29		;first ccp sector(128)
	 call	setsec		;set sector
	 mvi	c,0		;ccp/bdos track
	 call	settrk		;set track
w$read	 call	diskrd		;read one sector
	 ana	a		;set flags(ccr)
	 jrnz	w$eror		;exit if error
	 lda	bt$sec		;get sector number
	 cpi	72		;last SECTOR(128)
	 jz	warm		;go init page zero
	 inr	a		;next sector
	 sta	bt$sec		;store next sector
	 lxi	d,sec$sz	;sector size
	 lhld	bt$dma		;inc buffer pointer to next sec
 	 dad	d		;new buffer address 
	 shld	bt$dma		;store new buffer address
	 mvi	c,2ah		;
	 call	outCH		;splash progress bar
	 jr	w$read		;again

w$eror lxi	h,msg$le	;display error msg
	 call	msg$ot		;and
	 hlt			;halt

	else

	 jmp	warm		;do warm boot

	endif

eoinit	equ	$
;fill out directory buffer dir$buf

	org	dir$bf+80h

msg$so	db	cr,lf
sys$td	db	td$asc		;tens digit
sys$od	db	od$asc		;ones digit
		db	'K CPM 2.2-IH'
	if 	Banked22
		db	'-Banked'
	endif
	db	cr,lf+80h	;sign bit set on last byte

;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 exits and errors

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

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

seldsk:
	mov	a,c		;get drive no from c
	sta	bt$drv	;save drive no in bt$drv

	mov	a,e		;get log on request from e
	sta	log$rq	;save log on req in log$rq

	mov	l,c
	mvi	h,0
	dad	h		;drive no times 2 in HL
	lxi	d,dr$tbl	;base of Drive Table in DE
	dad	d		;pointer to DPH in HL
	mov	a,m		
	inx	hl
	mov 	h,m
	mov	l,a		;hl contains DPH of drive in c
	shld	dt$ptr	;store DPH
	jr	dsk$ok

;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		;de contains DPB
	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
punch	ret			;return

;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			;

;warm boot loads ccp + bdos sets up page zero

warm	lxi	sp,0080h	;set up stack in def buffer
	
	if	Banked22

	 mvi	a,0		;bank	0
	 out	0c0h		;expandoram ii bank select
	mvi	a,0c3h		;jmp xxxx = (c3 xx xx)
	sta	0		;
	lxi	h,bios+03	;jmp bios+3(warm)
	shld	1		;init warm vector in bank 0 so reset works
	 lxi	hl,8000h	;loc of ccp and bdos in bnk0
	 lxi	de,ccp		;loc of ccp and bdos in bnk1
	 lxi	bc,44*128	;size of ccp and bdos
	 ldir
;	 call 	block
	 mvi	a,1		;bank	1
	 out	0c0h		;expandoram ii bank select

	else

	 mvi	e,0	;1	;log on request
	 mvi	c,0		;drive 0
	 call	seldsk		;select drive
	 lxi	b,ccp		;cpm ccp address
	 call	setdma		;set dma
	 mvi	c,29		;first ccp sector(128)
	 call	setsec		;set sector
	 mvi	c,0		;ccp/bdos track
	 call	settrk		;set track
	
;read ccp and bdos
	 mvi	c,0dh		;
	 call	outCH		;cr
	 mvi	c,0ah		;
	 call	outCH		;lf

w$read	 call	diskrd		;read one sector
	 ana	a		;set flags(ccr)
	 jrnz	w$eror		;exit if error
	 lda	bt$sec		;get sector number
	 cpi	72		;last SECTOR(128)
	 jrz	w$zrpg		;go init page zero
	 inr	a		;next sector
	 sta	bt$sec		;store next sector
	 lxi	d,sec$sz	;sector size
	 lhld	bt$dma		;inc buffer pointer to next sec
	 dad	d		;new buffer address 
	 shld	bt$dma		;store new buffer address
	 mvi	c,2ah		;
	 call	outCH		;splash progress bar
	 jr	w$read		;again 

w$eror	 lxi	h,msg$le	;display error msg
	 call	msg$ot		;and
	 hlt			;halt
	endif

;init page zero

w$zrpg	mvi	a,0c3h		;jmp xxxx = (c3 xx xx)
	sta	0		;
	lxi	h,bios+03	;jmp bios+3(warm)
	shld	1
	sta	5		;jmp instruction
	lxi	h,bdos+06	;jmp bdos (ccp+6)
	shld	6
	sta	38h		;rst 7
	lxi	h,0e003h	;jmp sdmon(e003)
	shld	39h

;last logged drive

	lda	c$disk	;last drive used
	mov	c,a		;ccp expects it in c
	
	lxi	h,0080h	;set default dma
	shld	bt$dma	

;jump to ccp

	jmp	ccp		;go to cpm


;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

pc$dpb:	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$dpb:	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

;disk parameter block for 4 MB harddisk

hd$dpb:  DW    128		;sectors per track
	DB    4		;block shift factor
	DB    15		;block mask
	DB    0		;extent mask
	DW    2039		;disk size-1
	DW    1023		;directory max
	DB    255		;alloc 0
	DB    255		;alloc 1
	DW    0		;check size
	DW    0		;track offset

;messages

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

dr$tbl: dw      d0$dph
        dw      d1$dph
        dw      d2$dph
        dw      d3$dph
        dw      d4$dph
        dw      d5$dph
        dw      0
        dw      0
        dw      d8$dph
        dw      d9$dph
        dw      0
        dw      0
        dw      0
        dw      0
        dw      0
        dw      0 	;dF$dph


;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	pc$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	pc$dpb
	dw	d1$chk
	dw	d1$all
d2$dph:	dw	0
	dw	0
	dw	0
	dw	0
	dw	dir$bf
	dw	pc$dpb
	dw	d2$chk
	dw	d2$all
d3$dph:	dw	0
	dw	0
	dw	0
	dw	0
	dw	dir$bf
	dw	pc$dpb
	dw	d3$chk
	dw	d3$all
d4$dph:	dw	sdtran
	dw	0
	dw	0
	dw	0
	dw	dir$bf
	dw	sd$dpb
	dw	d4$chk
	dw	d4$all
d5$dph:	dw	sdtran
	dw	0
	dw	0
	dw	0
	dw	dir$bf
	dw	sd$dpb
	dw	d5$chk
	dw	d5$all
d8$dph:	dw	0
	dw	0
	dw	0
	dw	0
	dw	dir$bf
	dw	hd$dpb
	dw	d8$chk
	dw	d8$all
d9$dph:	dw	0
	dw	0
	dw	0
	dw	0
	dw	dir$bf
	dw	hd$dpb
	dw	d9$chk
	dw	d9$all

eob:	equ	$

;Un-initialized data area

	org	ui$data

; drive allocation area

all$pcsz equ	91
d0$all	equ	$
d1$all	equ	d0$all+all$pcsz
d2$all	equ	d1$all+all$pcsz
d3$all	equ	d2$all+all$pcsz
all$sdsz	equ	31
d4$all	equ	d3$all+all$pcsz
d5$all	equ	d4$all+all$sdsz
all$hdsz	equ	255
d8$all	equ	d5$all+all$sdsz
d9$all	equ	d8$all+all$hdsz

;changed disk area

chk$pcsz	equ	64

d0$chk	equ	d9$all+all$hdsz
d1$chk	equ	d0$chk+chk$pcsz
d2$chk	equ	d1$chk+chk$pcsz
d3$chk	equ	d2$chk+chk$pcsz
chk$sdsz	equ	16
d4$chk	equ	d3$chk+chk$pcsz
d5$chk	equ	d4$chk+chk$sdsz
chk$hdsz	equ	0
d8$chk	equ	d5$chk+chk$sdsz
d9$chk	equ	d8$chk+chk$hdsz

eoui	equ	d9$chk+chk$hdsz

	end