* NAM BOOT
*
* BASED ON BOOT CP/68 PROGRAM FOR ICOM 8 INCH FLOPPY DISK PROGRAM BY J. HEMENWAY 1979
* 
* MODIFIED BY ROBERTO SANCHO TO SUPPORT MF68 DISKS ON SWTPC SIMH EMULATION
* APR/2022
*
* UPDATED BY MIKE DOUGLAS TO RUN ON REAL HARDWARE JUL/2022
*
* SAVE AS TRANSIENT COMMAND AFTER LOADING BOOT.S19 INTO RAM WITH
*    SAVE BOOT.CMD,$2400,$2578,$256B
*
* DISK GEOMETRY: 35 TRACKS X 18 SECTORS X 128 BYTES
* TRACK 0 HAS SECTORS NUMBERED 0,1,2,4..18 (NO SECTOR 3, FIRST SECTOR IS ZERO)
* TRACK 1..34 HAS SECTORS NUMBERED 1,2..18
*
* TRACK 0: SECTORS 0,1,2: HOLDS THIS BOOT PROGRAM
* TRACK 0: SECTOR 4..18: DIRECTORY
* TRACK 1..34: DATA SECTORS FOR FILES
*
FDRSC	EQU	$0B		RESTORE
FDSKI	EQU	$1B		SEEK
FDRDC	EQU	$8C		READ A SECTOR

DRVREG	EQU	$8014		DRIVE REGISTER
CMDREG	EQU	$8018		COMMAND REGISTER	
TRKREG	EQU	$8019		TRACK REGISTER
SECREG	EQU	$801A		SECTOR REGISTER
DATREG	EQU	$801B		DATA REGISTER
*
* BOOT BEGINS HERE
*
	ORG $2400
*	
BOOT	JSR	DRIVE		SETUP DRIVE 0
	LDAA	#FDRSC		ISSUE RESTORE COMMAND
	STAA	CMDREG
	JSR	DEL30U		30 USEC DELAY
START2	LDAA	CMDREG
	BITA	#1		BUSY?
	BNE	START2		YES
*
* NOW GET SYSTEM LINK INFORMATION
*
	LDAA	#2		SECTOR=2
	LDAB	#0		TRACK=0	 
	LDX	#SECBUF
	JSR	RDSEC		READ LINK SECTOR
	LDX	#SECBUF+4
	STX	INDEX		INIT BUFFER INDEX
	LDX	#SECBUF
	LDAB	124,X		GET LAST TRACK
	LDAA	125,X		GET LAST SECTOR
	STAB	LTS
	STAA	LTS+1
	LDAB	122,X		GET FIRST TRACK
	BEQ	NOTLNK		BR TO NOT LINKED ERROR MSG
	LDAA	123,X		GET FIRST SECTOR
	STAB	FTS
	STAA	FTS+1
	JSR	RDSEC		READ FIRST SECTOR
*
* 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
*	
NOTLNK	LDX	#NBMSG		MESSAGE NOT LINKED
	JMP	PRERR		GO TO PRINT IT AND EXIT	
*
BOOT2	CMPA	#$02		DATA FRAME?
	BNE	BOOT4		NO
	BSR	GETBYT
	STAA	SAVEX		GET ADDRESS
	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
*
BOOT4	LDX	ADDRES		GET TRANSFER ADDRESS
	JMP	0,X		GO THERE
*
* READ A DATA BYTE FROM SYSTEM FILE
* RETURN BYTE IN A REGISTER
*
GETBYT	LDX	INDEX
	CPX	#SECBUF+128	NEED NEW SECTOR?
	BEQ	GETSEC		YES
GETB1	LDAA	0,X		GET BYTE 
	INX
	STX	INDEX		MOVE POINTER
	RTS
GETSEC 	LDAB	FTS		CURRENT TRACK
	LDAA	FTS+1		CURRENT SECTOR
	CMPA	LTS+1		CHECK FOR LAST SECTOR 
	BNE	GETS2		NOT LAST
	CMPB	LTS
	BNE	GETS2		NOT LAST
	BRA	BOOT4		EOF-GOTO TRANSFER ADDRESS
GETS2	LDX	#SECBUF
	LDAB	0,X		GET FWD LINK TRACK
	LDAA	1,X		GET FWD LINK SECTOR
	STAB	FTS		UPDATE CURRENT T/S
	STAA	FTS+1
	BSR	RDSEC
	LDX	#SECBUF+4
	BRA	GETB1
*
* SINGLE SECTOR READ ROUTINE
*
* DRIVE=0, TRACK=B, SECTOR=A, SECBUF=X
*
RDSEC	PSHA			SAVE SECTOR
	PSHB			SAVE TRACK
	STX	SAVEX2		SAVE BUFFER POINTER
	JSR	DRIVE		SETUP DRIVE 0
	LDX	SAVEX2		RESTORE BUFFER POINTER
	LDAA	#5		FIVE RETRIES
	STAA	RCNT
RDSEC2	PULB			GET TRACK
	PULA			GET SECTOR
	LDX	SAVEX2		GET BUFFER ADRESS
	PSHA
	PSHB		 	PUT BACK ON STACK 
RDSEC3	JSR	SEEK
	LDAA	#FDRDC	 	READ COMMAND
	STAA	CMDREG
	JSR	DEL30U		30 USEC WAIT
	LDAB	#128		SECTOR SIZE=128
READ1	LDAA	CMDREG
	BITA	#$02		DATA REG FULL?
	BNE	READ2		YES
	BITA	#1		BUSY?
	BNE	READ1		YES
	BRA	READ3		ERROR
READ2	LDAA	DATREG		GET A BYTE
	STAA	0,X		STORE IN BUFFER
	INX
	DECB
	BNE	READ1		DO AGAIN
READ3	LDAA	CMDREG
	BITA	#1		BUSY?
	BNE	READ3		YES
READ4	ANDA	#$1C		MASK OF STATUS BITS
	BEQ	READ5		GOOD?
	DEC	RCNT		NO, TRY AGAIN?
	BNE	RDSEC2
QUIT	JMP	ERROR		FAILED 5 TIMES, ERROR
READ5	PULB			CLEAN STACK
	PULA
	RTS			GOOD READ
*
* SEEK TRACK=B, SECTOR=A
*
SEEK	CMPB	TRKREG		ON TRACK?
	BEQ	SEEK2		YES
	STAB	DATREG		NO
	BSR	DEL30U
	LDAB	#FDSKI		SEEK COMMAND
	STAB	CMDREG
	BSR	DEL30U
SEEK1	LDAB	CMDREG
	BITB	#1		BUSY?
	BNE	SEEK1		WAIT UNTIL DONE
SEEK2	STAA	SECREG		SET SECTOR
*
* 30 USEC DELAY FOR CONTROLLER CHIP
*
DEL30U	INX
	DEX
	INX
	DEX
	INX
	DEX
	INX
	DEX
	RTS
*
* SELECT DRIVE 0
*
DRIVE	LDAB	CMDREG
	ANDB	#$80		READY? 
	BEQ	DRIVE1		YES
	LDX	#0000
DRV0	INX
	BNE	DRV0
DRV1	INX
	BNE	DRV1
	LDAB	CMDREG
	ANDB	#$80		READY?
	BEQ	DRIVE1		YES
DRIVE0	JMP	ERROR		NO, ERROR
DRIVE1	CLR	DRVREG		SET DRIVE=0
	BRA	DEL30U
*
* ERROR
*
ERROR	LDX	#EMSG
PRERR	JSR	$E07E		DISPLAY ERROR MSG USING SWTBUG PRINT STRING ROUTINE (PDATA1) 
	JMP	$E113		GO TO SWTBUG PROMPT
EMSG	FCC	'DISK ERROR'
	FCB	$0D,$0A,$04
NBMSG	FCC	'NOT LINKED'
	FCB	$0D,$0A,$04

MAXADD	EQU	*		THIS VALUE MUST BE < $257B
	
*
* ENTRY POINT WHEN EXECUTED AS A CP68 TRANSIENT COMMAND
*
CSTART	LDX	#PRERR2		CHANGE PRERR CALL FROM SWTBUG PRINT STRING ROUTINE TO PRERR2 
	STX	PRERR+1 
	JMP	BOOT		NORMAL START 
PRERR2	SWI	PRTMSG		PRINT STRING USING CP68 SVC CALL
	FCB	$31	
	SWI	WARMS		CP68 WARM START
	FCB	$1F
	
*
* VARIABLES:
*
SECBUF	RMB	128		SECTOR BUFFER
FTS	RMB	2		CURRENT T/S 
LTS	RMB	2		LAST T/S
INDEX	RMB	2		PTR TO NEXT BYTE TO GET FROM SECTOR BUFFER
SAVEX	RMB	2		TEMP
SAVEX2	RMB	2		TEMP
ADDRES	RMB	2		TRANSFER ADDRES (BOOTED PROG ENTRY POINT)
FCNT	RMB	1		COUNT OF BYTES IN LOADED PROG FRAME
RCNT	RMB	1		RETRY COUNT
	
	END
