* NAM BOOT
*
* ICOM CP/68 BOOTSTRAP PROGRAM
* ASSUMES SYSTEM FILE LINKED AS FOLLOWS:
*
*	TRACK 0, SECTOR 3, BYTE 122-FIRST TRACK
*				123-FIRST SECTOR
*				124-LAST TRACK
*				125-LAST SECTOR
*				126,7 FREE-SPACE HEADER
*
* BOOTS SYSTEM FROM DRIVE 0
*
* WRITTEN BY MIKE DOUGLAS IN THE STYLE OF THE ORIGINAL
* BOOT LOADER. REDUCED IN SIZE TO FIT INTO TWO SECTORS
* BECAUSE THAT IS ALL THE INIT PROGRAM ACTUALLY WRITES
* AND THE 680 BOOT ROM ONLY LOADS TWO SECTORS.
*
* AUGUST, 2022

PROMLOC	EQU	$FC00		BOOT AND I/O PROM
READSEC	EQU	PROMLOC+9	READ SECTOR ROUTINE
DOCMD	EQU	PROMLOC+12	EXECUTE 3712 COMMAND

* FD3712 CONTROLLER COMMANDS

CSTATUS	EQU	$00		READ STATUS
CREAD	EQU	$03		READ SECTOR
CWRITE	EQU	$05		WRITE SECTOR
CRDCRC	EQU	$07		VALIDATE SECTOR CRC
CSEEK	EQU	$09		SEEK TO TRACK
CCLRERR	EQU	$0B		CLEAR ERROR FLAGS
CRESTOR	EQU	$0D		SEEK TO TRACK 0
CSETTRK	EQU	$11		SET TRACK TO SEEK
CDRVSEC	EQU	$21		SET UNIT AND SECTOR
CWRTBUF	EQU	$31		WRITE BUFFER
CRDBUF	EQU	$41		READ BUFFER
CRESET	EQU	$81		RESET THE CONTROLLER

* FD3712 CONTROLLER STATUS BITS

SBUSY	EQU	$01		1=BUSY
SCRCERR	EQU	$08		1=CRC ERROR
SWRTPRT	EQU	$10		1=WRITE PROTECTED
SNOTRDY	EQU	$20		1=DRIVE NOT READY
SERROR	EQU	$29		ANY ERROR BIT EXCEPT WRITE PROTECT

* UIO INTERFACE BOARD
*   PIA #1 (IC-C) PORT A IS STATUS/DATA IN
*   PIA #1 (IC-C) PORT B IS COMMAND OUT
*   PIA #2 (IC-B) PORT A IS NOT USED
*   PIA #2 (IC-B) PORT B IS DATA OUT
*
*   COMMAND BIT 0 (THE EXECUTE BIT) COMES FROM THE OR OF
*   THE DATA-OUT AND DATA-IN HANDSHAKE LINES FROM THE PIAS.
*   CA2 FROM PIA #1 IS THE DATA-IN HANDSHAKE AND CB2 FROM
*   PIA #2 IS THE DATA-OUT HANDSHAKE.

UIOBASE	EQU	$F000	 	BASE ADDRESS OF UIO BOARD
P1ACSR	EQU	UIOBASE+$08	CONTROL/STATUS FOR FDC DATA IN
DATAIN	EQU	UIOBASE+$09	FDC DATA/STATUS IN (IC-C PORT A)
CMDOUT	EQU	UIOBASE+$0B	FDC COMMAND OUT (IC-C PORT B)
DATAOUT	EQU	UIOBASE+$0F	FDC DATA OUT (IC-B PORT B)

HSOFF	EQU	$3C		AUTO HANDSHAKE OFF
HSAUTO	EQU	$2C		AUTO HANDSHAKE ON
NUMTRK	EQU	77		NUMBER OF TRACKS ON DISK

* BOOT BEGINS HERE

	ORG	$2400

START	LDS	#STACK		INIT STACK POINTER
	LDAA	#$FF		TRACK THE DRIVE ON IS NOT KNOWN
	STAA	DRVTRK

* GET SYSTEM FILE LINK INFORMATION

	CLR	CURTRK		READ TRACK 0, SECTOR 3
	LDAA	#3
	STAA	CURSEC
	LDX	#SECBUF		INTO SECBUF
	JSR	RDSEC

	LDX	#SECBUF
	LDAA	122,X		GET FIRST T/S
	STAA	CURTRK
	LDAA	123,X
	STAA	CURSEC

	LDAA	124,X		GET LAST T/S
	STAA	ENDTRK
	LDAA 	125,X
	STAA	ENDSEC

	LDX	#SECBUF+4	DATA IN SECTOR STARTS AT OFFSET 4
	STX	INDEX
	LDX	#SECBUF		READ FIRST SECTOR OF THE SYSTEM FILE
	JSR	RDSEC

* NOW LOAD SYSTEM FILE INTO MEMORY

BOOT1	BSR	GETBYT		GET A DATA BYTE FROM FILE
	CMPA	#$16		TRANSFER-ADDRESS?
	BNE	BOOT2		NO

	BSR	GETBYT
	STAA	ADDRES		GET TRANSFER ADDRESS
	BSR	GETBYT
	STAA	ADDRES+1
	BRA	BOOT1		GET NEW DATA FRAME	

BOOT2	CMPA	#$02		DATA FRAME?
	BNE	JMPDOS		NO, ASSUME FINISHED

	BSR	GETBYT		GET DESTINATION ADDRESS
	STAA	SAVEX		SAVE IT IN SAVEX
	BSR	GETBYT
	STAA	SAVEX+1
	BSR	GETBYT
	STAA	FCNT		GET FRAME COUNTER

BOOT3	BSR	GETBYT		GET DATA BYTE
	LDX	SAVEX
	STAA	0,X		STORE BYTE
	INX
	STX	SAVEX
	DEC	FCNT
	BNE	BOOT3

	BRA	BOOT1		GET NEW DATA FRAME

JMPDOS	LDX	ADDRES		GET TRANSFER ADDRESS
	JMP	0,X		GO THERE

* RETURN A DATA BYTE FROM SYSTEM FILE IN A

GETBYT	LDX	INDEX		X->NEXT BYTE IN SECBUF
	CPX	#SECBUF+128	NEED NEW SECTOR?
	BNE	GETRET		NO, JUST RETURN NEXT BYTE

	LDAA	CURSEC		CHECK FOR LAST SECTOR
	CMPA	ENDSEC
	BNE	GETS2		NOT LAST

	LDAA	CURTRK		CHECK FOR LAST TRACK
	CMPA	ENDTRK
	BEQ	JMPDOS		EOF, GO TO TRANSFER ADDRESS

GETS2	LDX	#SECBUF		GET NEXT T/S IN FILE
	LDAA	0,X
	STAA	CURTRK
	LDAA	1,X
	STAA	CURSEC
	BSR	RDSEC		READ THE NEXT FILE SECTOR
	LDX	#SECBUF+4	X->DATA PORTION OF SECTOR
	
GETRET	LDAA	0,X		RETURN NEXT BYTE
	INX
	STX	INDEX		MOVE POINTER
	RTS

* SINGLE SECTOR READ ROUTINE

RDSEC	JSR	SEEK		SEEK TO TRACK AND SET SECTOR
	BNE	FAIL		FAILED, START OVER

	LDAA	#5		FIVE RETRIES
	STAA	RCNT
	
RDRTRY	JSR	READSEC		READ SECTOR IS IN THE BOOT PROM
	BEQ	RETURN		GOOD READ	
	DEC	RCNT		ELSE, TRY AGAIN
	BNE	RDRTRY
	
FAIL	JMP	START		FAILED 5 TIMES, START OVER

* SEEK - SEEK TO CURTRK AND SET SECTOR TO CURSEC. RETURNS
*    NON-ZERO STATUS IF AN ERROR OCCURS.

SEEK	LDAB	CURSEC		B=REQUESTED SECTOR
	ANDB	#$1F		LIMIT RANGE
	LDAA	#CDRVSEC	SELECT DRIVE 0 AND SET SECTOR
	JSR	DOCMD

	LDAB	CURTRK		B=REQUESTED TRACK
	CMPB	DRVTRK		SAME TRACK DRIVE IS ON?
	BEQ	RETURN		YES, DO NOTHING

	CMPB	#NUMTRK		VALID TRACK?
	BHS	SEEKERR		NO
	STAB	DRVTRK		ELSE SAVE NEW DRIVE TRACK
	BEQ	SEEK0		USE RESTORE FOR TRACK 0, NOT SEEK
	
	LDAA	#CSETTRK	SET DESIRED TRACK NUMBER
	JSR	DOCMD
	LDAA	#CSEEK		SEEK TO TRACK
	JMP	DOCMD		EXECUTE AND RETURN TO CALLER

SEEK0	LDAA	#CRESTOR	ISSUE RESTORE TO TRACK 0 COMMAND
	JMP	DOCMD		EXECUTE AND RETURN TO CALLER
	
SEEKERR	LDAA	#$FF		RETURN WITH ERROR STATUS
RETURN	RTS

		
* DATA AREA

SECBUF	RMB	128		SECTOR BUFFER
CURTRK	RMB	1		CURRENT TRACK BEING READ
CURSEC	RMB	1		CURRENT SECTOR BEING READ
ENDTRK	RMB	1		LAST TRACK IN THE SYSTEM FILE
ENDSEC	RMB	1		LAST SECTOR IN THE SYSTEM FILE
DRVTRK	RMB	1		TRACK THE DRIVE IS ACTUALLY ON
INDEX	RMB	2		PTR TO NEXT BYTE TO GET FROM SECBUF
ADDRES	RMB	2		TRANSFER ADDRESS (BOOTED PROG ENTRY POINT)
FCNT	RMB	1		COUNT OF BYTES IN LOADED PROG FRAME
RCNT	RMB	1		READ RETRY COUNT
SAVEX	RMB	2
	RMB	15		STACK SPACE
STACK	RMB	1

	END
