*****************************************************************************
;
; Cold boot loader for CP/M 2.2 on the FD3712 dual drive cabinet
;
;    This version expects the modified disk PROM that runs at F400h and
;    does not require RAM above the PROM.
;
;    This code is loaded into RAM at 80h from track 0, sector 1 of 
;    drive 0 by the boot PROM. The program then reads the CP/M image
;    from the remaining sectors of track 0 and all of track 1 into
;    high RAM. Finally, control is passed to the cold start entry 
;    point in the BIOS.
;
;    To patch this boot loader into a CP/M image created and saved
;    after running MOVCPM, use the following commands:
;
;	A>DDT CPM56.COM    (specify the saved CP/M image file)
;	-IBOOT.HEX
;	-R880
;	-G0		   (Go zero, not "oh")
;
;	Ver	  Date		     Description
;	---   ----------   ------------------------------------------
;	1.0   02/10/2021   Mike Douglas, original, based on disas-
;			   sembly of the boot loader for CP/M 1.4
;
;	1.1   09/06/2021   Mike Douglas, Update for new disk PROM
;			   at F400h
;
;****************************************************************************

;  Assembly options (set these to match the BIOS)

MEMSIZE	equ	56		;memory size in K bytes
BIOSLEN	equ	400h		;length of BIOS
ROMBASE	equ	0F400h		;location of disk PROM

;  CP/M equates

CCPLEN	equ	0800h		;CPM 2.2 fixed length
BDOSLEN	equ	0E00h		;CPM 2.2 fixed length
BIOSBAS	equ	MEMSIZE*1024 - BIOSLEN
BDOSBAS	equ	BIOSBAS-BDOSLEN
CCPBASE	equ	BDOSBAS-CCPLEN

; Disk equates

SECLEN	equ	128		;sector length
NUMSEC	equ	26		;sectors per track

;-----------------------------------------------------------------------------
; Disk PROM jump table 
;-----------------------------------------------------------------------------
	org	ROMBASE		;interface board PROM vector base
	
pBOOT	ds	3		;cold boot
pCOLD	ds	3		;cold start from CP/M
pWARM	ds	3		;warm start from CP/M
pHOME	ds	3		;move head to home position
pSELDSK	ds	3		;select disk
pSETTRK	ds	3		;set track number
pSETSEC	ds	3		;set sector number
pSETDMA	ds	3		;set dma address
pREAD	ds	3		;read sector
pWRITE	ds	3		;write sector

;--------------------------------------------------------------------------
; cpmBoot - Load the CP/M disk image from track 0 sectors 2-26
;    and then from track 1 sectors 1-26 into RAM. An interleave
;    of 2 is used to read the image.
;--------------------------------------------------------------------------
	org	80h		;load address

cpmBoot	lxi	sp,STACK	;init stack pointer

	mvi	c,0		;select drive 0
	call	pSELDSK	
	mvi	c,0		;set track 0
	call	pSETTRK
	
	lxi	h,CCPBASE+SECLEN   ;HL=address for trk 0, sec 3
	mvi	a,3		;start on sector 3
	call	loadTrk		;load track 0

	mvi	c,1		;step to track 1
	call	pSETTRK
	
	lxi	h,CCPBASE+SECLEN*(NUMSEC-1)  ;HL=address for trk 1, sec 1
	mvi	a,1		;start on sector 1
	call	loadTrk		;load track 1
	
	jmp	BIOSBAS		;enter the loaded BIOS
	
;--------------------------------------------------------------------------
; loadTrk - Load the current track starting on the sector passed 
;   in C. The starting sector should be odd. Every other sector is
;   read (e.g., 3,5,7...25,2,4,6...24,26).
;--------------------------------------------------------------------------
loadTrk	mov	c,a		;C=sector		

	mov	a,h		;A=MSB of next address to read
	cpi	MEMSIZE shl 2	;compare to BIOS end as K bytes
	jnc	ltSkip		;past BIOS, skip read

	push	h		;preserve HL and BC
	push	b	
	call	pSETSEC		;set sector
	
	mov	b,h		;set DMA address 
	mov	c,l
	call	pSETDMA		;set address
	
	call	pREAD		;read sector
	pop	b		;restore BC and HL
	pop	h
	jnz	cpmBoot		;start over if read error

ltSkip	lxi	d,2*SECLEN	;interleave of 2
	dad	d		;HL->address for next sector
	
	mvi	a,2		;interleave of 2
	add	c
	cpi	NUMSEC+1	;past last sector?
	jc	loadTrk		;no, read next sector

	sui	NUMSEC-1	;wrap around last sector
	lxi	d,-(SECLEN*(NUMSEC-1))
	dad	d		;compute address after wrap
	cpi	2		;first wrap?
	jz	loadTrk		;yes, keep going
	
	ret

; Data area

	ds	32		;stack space
STACK	equ	$
	
	end
