*------------------------------------------------------------------
*  PERBOOT.ASM
*     Flex program to install the Flex loader for the Percom
*     FDC into sector 0, track 0. After running PERBOOT, run
*     "LINK PERFLEX.SYS" to point the loader to the Pertec
*     version of the Flex system file.
*
*     Mike Douglas, 03/11/2020
*------------------------------------------------------------------

* Flex equates

BOOTLOC	equ	$2400		;Flex boot loader runs here

WARMST	equ	$AD03		;Flex warm start entry point
GETCHR	equ	$AD15		;get and return character in A
PUTCHR	equ	$AD18		;display character in A
INBUFF	equ	$AD1B		;input line to the line buffer
PSTRNG	equ	$AD1E		;display $04 terminated string
PRCRLF	equ	$AD24		;display CR/LF
GETFIL	equ	$AD2D		;get file spec from line bufer
OUTDEC	equ	$AD39		;display X as decimal value
OUTHEX	equ	$AD3C		;display X as hex value
GETHEX	equ	$AD42		;get hex value in X from line buffer
INDECM	equ	$AD48		;get decimal value in X from line buf

DREAD	equ	$BE80		;disk read sector
DWRITE	equ	$BE83		;disk write sector
DDRVSEL	equ	$BE8C		;disk drive select

* Misc Equates

CR	equ	$0D		;carriage return
LF	equ	$0A		;line feed
EOT	equ	$04		;end of string

*********************************************************************
*
* The PERBOOT program starts here ($2200)
*
*********************************************************************
	org	BOOTLOC-$200

	bra	perBoot		;skip by version number
version	fcb	1		;version 1	

perBoot	ldx	#mPrompt	;display confirmation prompt
	jsr	PSTRNG
	
	jsr	GETCHR		;get response
	anda	#$5F		;convert 'y' to 'Y'
	cmpa	#'Y'
	bne	abort		;don't do the update

	jsr	INDECM		;get drive number from command line
	bcs	badDrv		;invalid or missing drive number
	tstb			;only a separator present?
	beq	badDrv		;yes, comma or similar found

	stx	drvNumX		;save number entered
	ldaa	drvNumX+1	;use just LSB of drvNumX
	cmpa	#2		;verify 0 or 1
	bcc	badDrv

	ldx	#flxFcb		;point X to the FCB
	jsr	DDRVSEL		;select the drive

	ldx	#flxBoot	;point to the Flex boot loader
	ldaa	#0		;track 0
	ldab	#1		;sector 1 (0/1 are same on track 0)
	jsr	DWRITE		;write boot sector
	bne	wrtFail		;write failed

	ldx	#mDone		;display "drive updated" message

dspExit	jsr	PSTRNG		;display message in (X)
	jsr	PRCRLF		;extra CR/LF
	jmp	WARMST		;return to FLEX

wrtFail	ldx	#mFail		;"write to disk failed" then exit
	bra	dspExit		

badDrv	ldx	#mBadDrv	;"invalid drive" then exit
	bra	dspExit

abort	ldx	#mAbort		;"no updates performed" then exit
	bra	dspExit

*------------------------------------------------------------------
* Data Area
*------------------------------------------------------------------
mPrompt	fcb	LF
	fcc	'THIS PROGRAM WRITES THE FLEX LOADER FOR THE'
	fcb	CR,LF
	fcc	'PERCOM FDC TO TRACK 0 SECTOR 0.'
	fcb	CR,LF,LF
	fcc	'CONTINUE? '
	fcb	EOT

mBadDrv	fcc	'INVALID OR MISSING DRIVE NUMBER'
	fcb	EOT

mDone	fcc	'FLEX LOADER WRITTEN'
	fcb	CR,LF,LF
	fcc	'NOW RUN "LINK PERFLEX.SYS" TO POINT'
	fcb	CR,LF
	fcc	'THE LOADER TO THE PERFLEX.SYS file.'
	fcb	EOT

mFail	fcc	'WRITE TO DISK FAILED - '

mAbort	fcc	'NO UPDATES PERFORMED'
	fcb	EOT
		
flxFcb	equ	*		;Flex FCB structure
	fcb	0,0		;drive number at offset 3
drvNumX	rmb	2		;16 bit drive number from X


*------------------------------------------------------------------
*  FLEXLOAD.ASM
*      Flex 2.0 loader for Percom LFD-400 controller
*
*      Mike Douglas, 03/04/2020
*------------------------------------------------------------------
SSTACK	equ	$A07F		;system stack location

RDSEC	equ	$C00C		;read a sector (MiniDOS EPROM)
WTSEC	equ	$C00F		;write a sector (MiniDOS EPROM)

* Page 0 data maintained by MiniDOS

	org	0
drvNum	rmb	1		;drive number in MS 2 bits
trk	rmb	1		;desired track
sctr	rmb	1		;desired sector

bakLnk	rmb	2		;file backward link
fwdLnk	rmb	2		;file forward link
bytCnt	rmb	1		;sector byte count
addres	rmb	2		;data address vector
filTyp	rmb	1		;file type code	
ckSum	rmb	2		;sector checksum
postAm	rmb	2		;post amble

crnTrk	rmb	1		;current track
trkTbl	rmb	4		;track each drive is on
wrtAddr	rmb	2		;write buffer address
rdAddr	rmb	2		;read buffer address

*------------------------------------------------------------------
* Boot ROM jumps here after loading this from sector 0
*------------------------------------------------------------------
	org	BOOTLOC		;boot ROM puts this program here

flxBoot	lds	#SSTACK		;init stack pointer
	bra	loadFlx		;go load Flex

flexTrk	fcb	1		;track for FLEX2.SYS
flexSec	fcb	10		;sector for find FLEX2.SYS
			
pFlex	rmb	2		;pointer to Flex entry address
pDest	rmb	2		;pointer to destination in memory
pSource	rmb	2		;pointer to data in secBuf

*------------------------------------------------------------------
* loadFlx - Entry point for loading Flex from disk. The drive
*    that loaded this program is used to load Flex. This allows
*    booting from any drive.
*------------------------------------------------------------------
loadFlx	bsr	read1st		;read first sector of Flex

load1	bsr	getByte		;get next byte

	cmpa	#$02		;data record header?
	beq	load2

	cmpa	#$16		;transfer address header?
	bne	load1		;loop if neither

	bsr	getByte		;get transfer address
	staa	pFlex		;MSB
	bsr	getByte		;LSB
	staa	pFlex+1

	ldx	pFlex		;jump to Flex
	jmp	0,x

load2	bsr	getByte		;A=load address MSB
	psha
	bsr	getByte		;A=load address LSB
	pulb			;B=load address MSB

	staa	pDest+1		;save load address LSB
	stab	pDest		;MSB

	bsr	getByte		;A=byte count
	tab			;B=byte count
	beq	load1		;byte count was zero

load3	pshb
	bsr	getByte		;get next data byte
	pulb

	ldx	pDest		;X->where to put the data
	staa	0,x
	inx
	stx	pDest

	decb
	bne	load3		;loop for byte count in B

	bra	load1		;get next record

*------------------------------------------------------------------
* readSec 
*------------------------------------------------------------------
read1st	ldaa	flexTrk		;read 1st sector of Flex
	ldab	flexSec

readSec	staa	trk		;give track to MiniDOS

	ldx	#skewTbl-1	;X->sector skew table w/1-index
	stab	*+4		;modify the following index offset
	ldab	0,x		;B=physical sector
	stab	sctr		;give sector to MiniDOS

	ldx	#secBuf		;X->secBuf
	stx	rdAddr		;give buffer address to MiniDOS

	clr	bytCnt		;read 256 bytes

	jsr	RDSEC		;read sector in MiniDOS
	bcs	flxBoot		;error, start over

	ldx	#secBuf+4	;data starts at offset 4
	stx	pSource		;init source pointer

	rts

* skewTbl maps logical sectors 1-10 to physical sectors 0-9 with
*    a skew of 5.

skewTbl	fcb	0,5,1,6,2,7,3,8,4,9

*------------------------------------------------------------------
* getByte - Get next byte from sector buffer. Retrieve next
*    sector as needed.
*------------------------------------------------------------------
getByte	ldx	pSource		;X->next byte 
	cpx	#secBuf+256	;reached end of sector buffer?
	beq	nextSec		;yes, get the next sector

	ldaa	0,x		;otherwise, return the next byte
	inx
	stx	pSource		;save updated pointer
	rts

nextSec	ldaa	secBuf		;A=next track
	ldab	secBuf+1	;B=next sector
	bsr	readSec
	bra	getByte

* Sector buffer starts here

secBuf	equ	*

	end
