;
; LOADKEY -- Commodore 128 -- Version 2.0
;
; Loads key definitions from a disk file.
;
;	Usage:	LOADKEY {{d:}<fn>}
;
; The file must have a .KEY filetype.  If a filename is not given
; in the command line, it will be requested.  If a drive is not
; given, the current drive is assumed.
;
;	Eugene L. Pizzetta
;	481 Revere Street
;	Revere, MA  02151
;	(617) 284-0891
;
; Assemble with MAC and load with HEXCOM.  Z80.LIB required.
;
;
Bdos	equ	0005h		; Bdos entry
WBoot	equ	00h		; warm boot
BELL	equ	07h		; BEL
CR	equ	0Dh		; carriage return
DBuff	equ	0080h		; default buffer
DskBuf	equ	01000h		; disk dma address (Bank 1)
Fcb	equ	05Ch		; default file control block
FcbDr	equ	Fcb		; drive
FcbEx	equ	Fcb+0Ch		; extent
FcbName	equ	Fcb+1		; filename
FcbType	equ	Fcb+9		; filetype
KeyBuf	equ	01000h		; key table address (Bank 0)
LF	equ	0Ah		; linefeed
MvSize	equ	080h		; bytes to move (128 maximum interbank)
TPA	equ	0100h		; program load address
Fail	equ	0FF00h		; program failure code
;
; BDOS service functions
;
PrStr	equ	9
GetStr	equ	10
FOpen	equ	15
FClose	equ	16
FRead	equ	20
SetDma	equ	26
FMulti	equ	44
BdosRet	equ	108
ParseFn	equ	152
;
; BIOS services (jump table)
;
BiosMv	equ	0F04Bh		; block move
BiosXmv	equ	0F057h		; set source and destination banks
;
;
; Macros
;
	MACLIB	Z80
;
BLKMOVE	MACRO	FROM,TO,LENGTH
	lxi	h,FROM
	lxi	d,TO
	lxi	b,LENGTH
	LDIR
	ENDM
;
;
;
	org	TPA
	jmp	MAIN
;
MSG1:	db	CR,LF,'LOADKEY    Commodore 128    v 2.0$'
MSG2:	db	CR,LF,LF,'Load key definitions from file: $'
MSG3:	db	CR,LF,LF,'File Not Found',BELL,CR,LF,'$'
MSG4:	db	CR,LF,LF,'DONE$'
;
DFCB:	db	0,'        '
KTYPE:	db	'KEY'
BLANK:	db	'              '
;
PFCB:	dw	DBuff+2
	dw	Fcb
;
COUNT:	db	0
;
MAIN:	lxi	d,MSG1		; print sign-on
	call	PRINT
;
	lda	Fcb+1		; check for command tail
	cpi	'A'
	JRNC	ISFILE		; tail found
	lxi	d,MSG2		; if not, print message
	call	PRINT
	BLKMOVE	DFCB,FCB,36	; clear FCB
	BLKMOVE	BLANK,DBuff+2,14
	mvi	a,14
	sta	DBuff
	lxi	d,DBuff
	call	GETS
	call	PARSE		; parse it, and
	lxi	h,FcbName	; make sure it's uppercase
	mvi	b,08
	call	UPCASE
;
ISFILE	BLKMOVE	KTYPE,FcbType,3	; type: .KEY
	call	OPEN
	inr	a		; does file exist
	JRNZ	RDFILE		; if so, read it
	lxi	d,MSG3		; if not, print message
	call 	PRINT
	mvi	c,BdosRet	; send failure code
	lxi	d,Fail		; ..to the BDOS
	call	Bdos
	jmp	EXIT		; and abort
;
RDFILE:	mvi	c,SetDma	; set DMA for disk write
	lxi	d,DskBuf
	call	Bdos
	mvi	c,FMulti	; set multi-sector write
	lxi	d,0008h
	call	Bdos
	call	READ
	call	CLOSE
;
	lxi	d,DskBuf	; starting source address
	lxi	h,KeyBuf	; starting target address
	mvi	a,0		; set count to 0
AGAIN:	sta	COUNT		; store count
	call	BNKSET		; set for interbank move
	call	BNKMOV		; then move it
	lda	COUNT		; get count
	inr	a		; increment it
	cpi	8		; eight times yet?
	JRNZ	AGAIN		; if not, go again
;
	lxi	d,MSG4		; say goodbye
	call	PRINT
EXIT:	jmp	WBoot		; return to CCP
;
;
BNKSET:	mvi	c,1		; source bank in C
	mvi	b,0		; destination bank in B
	call	BiosXmv		; set for interbank move
 	ret
;
BNKMOV:	lxi	b,MvSize	; bytes to move in BC
	call	BiosMv		; call for interbank move
	ret
;
CLOSE:	mvi	c,FClose	; close file
	lxi	d,Fcb
	call	Bdos
	ret
;
GETS:	mvi	c,GetStr	; get string to address
	call	Bdos		; pointed to in DE
	ret
;
OPEN:	lxi	d,Fcb		; open file
	mvi	c,FOpen
	call	Bdos
	ret
;
PARSE:	lxi	d,PFCB		; parse string in DBUFF
	mvi	c,ParseFn	; to FCB filespec
	call	Bdos
	ret
;
PRINT:	mvi	c,PrStr		; print string, pointed to
	call	Bdos		; by DE, at console
	ret
;
READ:	mvi	c,FRead		; read file into buffer
	lxi	d,Fcb
	call	Bdos
	ret
;
UPCASE:	mov	a,m		; make uppercase
	ani	05Fh
	inx	h
	DJNZ	UPCASE
	ret
;
	end
