  .title	'Cold Boot loader for DMS/3,4 8-inch hard disks'
  .sbttl	'Hd8 cold loader'
  .ident	HBOOT8
.if1,[.prntx	'DMS/3,4 hard disk cold boot loader']


version ==	22	; corresponds to BIOS 2.2---
revision==	48	;		      -.-48-
patch	==	'b'	;		      -.---b

; Hard disk bootstrap loader
; This code is stored on track 2, sectors 1 and 2
;
;	***  to create and store hboot.com:
; A>zdti	    
; -f100 800 0 
; -ihboot8.hex
; -r7100
;
; -^C
; A>save 2 hboot8.sys	  OR   A>save 2 mboot8.sys
; A>wrun0 hboot8.sys 2 1  OR   A>wrun0 mboot8.sys 2 1
;
; Revision history:
;
;	  1.426  Initial release
;	  1.427  Added serial number
;	  1.429  Works with DSC/4
;	  1.435  Master code moved to tracks 5 and 6
;		 add version, revision and patch
;	  2.247a Separated Boot  
;		 Loader is now >128 bytes, so the
;		 first 128-byte record is a loader
;		 loader for the rest.
;	  2.247b Change compile time options for 
;		 default bios names
;
; 2.248b  03/15/84 (dsb)  Various changes so that 
;		DSC-4 has RAM to work in
;

.page
; Conditional assembly option:
ALONE =\      "
Enter 0 to load stand-alone system (filename 88CABIOS)
      1 to load HiNet master (filename 88CMBIOS)
      2 to load HiDos master (filename 88HMBIOS) "
CMASTER ==	1-ALONE
HMASTER ==	2-ALONE


; Data and address definitions:
;
cmdHARD ==	3E7h	; PROM routine
resHARD ==	3EAh	; PROM routine
recHARD ==	3F0h	; PROM routine
SETMAP	==	03h
ONMAP	==	00h
OFFPROM ==	02h
;
track	==	02h	; System Directory location
sector	==	09h
entSIZE ==	24
nument	==	128
DIRsize ==	entSIZE ; = entsize * nument / secsize
DIRbase ==	8000h	; put it down out of the way

cr	==	0Dh
lf	==	0Ah
.page

	.pabs
	.phex
	.loc	9000h	; loader loader
;------------------------------------------------------- 
; The PROM has only read in 128 bytes of this program.
; Before do anything else we must read in the rest.  In
; order that we don't have to do anything heroic to
; put the two parts onto the disk, we will waste some
; room between the end of the first part and the start
; of the second part, and write it all as one file.
;-------------------------------------------------------

	lxi	H,memmap    ; Setup memory map for DSC/4
	lxi	B,0<8+SETMAP
domap:	outi
	mvi	A,11h
	add	B
	mov	B,A
	jrnz	domap
	in	ONMAP
			; now prepare for the read.  The
			; disk and DMA addresses are set
			; to read the rest of the loader
	mvi	B,2	; (figure on two more sectors)
	call	readfile
	jmp	PART2	; continue in next record

;------------------------------
; Read a file from Unit 0 (command block set up)
; Regs in:  B = number of sectors to read
; Regs out: none

readfile:
	push	B
	lxi	H,READhard
	call	cmdHARD ; send command to controller
	call	resHARD ; check status

	lhld	READadr ; buffer address
	push	H
	mvi	B,128	; bytes to read
	call	recHARD ; get buffer from harddisk
	pop	H

	lxi	B,128
	dad	B
	shld	READadr

	lxi	H,READsec
	inr	M	; increment to next sector
	mvi	A,81h	; see if end of track yet
	cmp	M
	jrnz	..next
	mvi	M,1	; restore sector number to 1
	inx	H
	inr	M	; increment track
..next:
	pop	B	; see if whole thing is in
	djnz	readfile
	ret
;-------------------------------
; Default memory map
memmap: .byte	0FFh,000h,0F1h,0F2h
	.byte	0F3h,0F4h,0F5h,0F6h
	.byte	0F7h,0F8h,000h,0FAh
	.byte	0FBh,0FCh,0FDh,0FEh
;------------------------------
; Hard disk command
READhard:
	.byte	11h	; read command
READsec:.byte	2	; initialize to read second
READtrk:.word	2	; and subsequent sectors of
	.byte	0	; this loader.
	.byte	0
	.byte	10	; retries
	.byte	0
READadr:.word	PART2	; read buffer address

.ifg (.-PART2),[.prntx 'Loader Loader is TOO LONG !']
	.page

	.loc	9080h
PART2:			    ; read System Directory
	lxi	H,track
	shld	READtrk
	mvi	A,sector
	sta	READsec
	lxi	H,DIRbase
	shld	READadr
	mvi	B,DIRsiz   ; number of records
	call	readfile   ; get the system directory	
;
; Now search the directory for our right file to boot on

	lxi	H,DIRbase	; begin of 1st entry
	mvi	B,nument	; num of entries
..srch: push	H
	push	B
	call	match		; see if same name
	pop	B
	pop	H
	jrz	..boot
	lxi	D,entSIZ
	dad	D
	djnz	..srch

; if we get here we are dead, like a dog.
	rst	4	    ; crlf
	lxi	H,missing
	rst	3	    ; output message
	rst	7	    ; restart monitor
	 
;--------------------
; File found, go ahead and read it in.
..boot:
	lxi	D,10	; space past name,vol,part
	dad	D
	mov	E,M	; get track into DE
	inx	H
	mov	D,M
	sded	READtrk ; make it "current"
	inx	H
	mov	A,M	; sector into A
	sta	READsec ; store it too
	inx	H	; assume <256 sects!
	mov	B,M	; get # of sects into B
	inx	H	; toss high byte of length
	inx	H	; low byte of load addr
	mov	E,M
	inx	H	; 2nd byte of load addr
	mov	D,M
	sded	READadr ; save load address
	push	D	; also save it here
	inx	H	; 3rd byte of load addr
	inx	H	; high byte of load addr
	inx	H	; low byte of entry offset
	mov	E,M
	inx	H	; high byte of entry offset
	mov	D,M
	push	D	; save entry offset

	call	readfile; go read file (e.g. BIOS)

; Move the rest of this code to real RAM

	lxi	H,movit
	lxi	D,DIRbase ; use this again
	lxi	B,lmove
	ldir
	jmp	DIRbase

; Map out pages 0 and 9, and map out PROM

movit:	lxi	H,0	; base of PROM
	lxi	D,4000h ; rescue the image by
	lxi	B,800h	; moving it up here
	push	B
	push	D
	push	H
	ldir

	lxi	B,0<8+SETMAP ; put some RAM there
	mvi	A,0F0h
	outp	A
	in	OFFPROM      ; turn on the RAM

	pop	D	; move the PROM image back
	pop	H	; (much separated boot stuff
	pop	B	; keeps it available until the	
	ldir		; last minute so we'll do it
			; that way here too)

	pop	D	; get code offset
	pop	H	; get load address
	dad	D	; sum = where to jump to

	lxi	B,90h<8+SETMAP ; now it's ok to swap real
	mvi	A,0F9h	     ; RAM into this segment
	outp	A
;
	lixd	03FEh	; get PROM serial number
	liyd	0400h	; including new part
	pchl		; jump to the BIOS
lmove	==	.-movit
;-------------------------
; try and match a file name.
; Regs in:  HL = ptr to unknown
; Regs out: Z if match, NZ if not
; Trashed:  all
match:
	lxi	D,filename
	mvi	B,8
..cmp:	ldax	D
	cmp	M
	rnz		
	inx	H
	inx	D
	djnz	..cmp
	ret
missing:
	.ascii	"HBOOT v. "
	.byte	(version/10)+ '0'
	.byte	(version@10)+ '0'
	.byte	(revision/10)+ '0'
	.byte	(revision@10)+ '0'
	.byte	patch 
 
	.ascii [cr][lf]"Can't find "
filename:
.ife ALONE,  [.asciz "88CABIOSS"] ; repeat last char	
.ife CMASTER,[.asciz "88CMBIOSS"] ; as AZM sometimes
.ife HMASTER,[.asciz "88HMBIOSS"] ; loses it

.if2,[
    .ifg (.-PART2-100h),[.prntx 'code is TOO LONG!']
			[.prntx 'code length is ok']
     .prntx 'finished DMS/3,4 cold boot loader' 
     ]

	.end
rntx 'code is TOO LONG!'