;
;	KOSONE BOOTLOADER ROUTINE - PC COMPATIBLE
;
;  	Boot loader routine for the Sage/Stride computer, 
;	  written Sept 1987 by Bill Kibler some portions 
;	  supplied from HTPL sample BIOS: BIOSAMPL.ASM.
;
;	The Sage computer loads sector 1 and 2 when given 
;	a boot command "IF". Each sector is 512 bytes long.
;	The first four bytes of the boot sector must contain
;	the word "BOOT" or the boot loader in the PROM will
; 	error out. The code is loaded at 0400hex and the program
;	will jump to 0404h after checking for "BOOT". Also these
;	sectors 1 and 2 are logical blocks, 0 and 1 (!). The 
;	Sage PROM reads sectors by logical block numbers not
;	track, side, and sector.
;
;	The PC disk format is compatible as far as sector and 
;	track utilization. The PC uses only the first sector for 
;	boot loader with the FATs starting at sector two. PCs use 
;	Clusters of two sectors to a block while the Sage is
;	one sector per block for the floppy disks. This will 
;	require doubling of the cluster number and subing one
;	to get the proper sector number for passing to the 
;	Sage FDREAD routines.
;
;	The program loads ONLY the FIRST FAT and FIRST DIR
;	sector, to save space. This means that the SYSTEM.BIO
;	or BIOS file must be load within the first 15 files!
;	The BIOS code is loaded at A00h, space between 400h
;	and A00h can be used after BIOS is completely loaded.
 
;
	TITLE	"SAGE BOOT.ASM PC COMPATIBLE BOOTSTRAP LOADER"
********************** ORIGINS *********************************
BOOT		EQU	00000004H
BOOT_CODE	EQU	00000400H	;BOOTER LOCATION
BOOT_VAR	EQU	000005E0H	;SCRATCH AREA
BOOT_FAT	EQU	00000600H	;FAT READ WITH BOOT
BOOT_DIR	EQU	00000800H	;DIR 1 LOCATION
BIOS_CODE	EQU	00000A00H	;BIOS CODE
TERMTEXT	EQU	00FE0018H	;PRINTOUT TEXT STRING
TERMCRLF	EQU	00FE001CH	;PRINTOUT CRLF
FDREAD		EQU	00FE0028H	;READ FLOPPY DISKETTE
TOTRACK		EQU	40		;TRACKS PER DISK
TOTSECT		EQU	9		;SECTORS PER DISK
TOTSIDE		EQU	2		;SIDES PER DISK
DEBUG		EQU	00FE0010H	;DEBUG ENTRY
**************** SYSTEM INITIALIZATION *************************
	ORG	BOOT_CODE
;
	DC.B	"BOOT"	; Sage checks for this statement
;
;	PROM starts program here...
;
	LEA	BOOT_VAR,A3
	MOVE.L	(A7)+,RTNADD(A3)
	MOVE.W	(A7)+,DRIVE(A3)
;
	JSR	TERMCRLF	;flag to booting is going on
	LEA	INITMSG,A0
	JSR	TERMTEXT
	JSR	TERMCRLF
;
	MOVE.W	#5,-(A7)	;load first DIR sector
	LEA	BOOT_DIR,A0	;DIR load location
	MOVE.L	A0,DIRPN(A3)	;ALSO LOAD DIRPOINTER
	MOVE.L	A0,-(A7)	;PUSH location on stack
	MOVEA.W	#512,A0		;one sector load
	MOVE.L	A0,-(A7)	;PUSH sector length
	MOVE.W	DRIVE(A3),-(A7)	;PUSH drive number
	JSR	FDREAD		;go read sector
	
	BNE.S	ABORT		;go debugger if error
;
;------------------------------- LOAD BIOS
	LEA	BOOT_VAR,A3	;setup pointer
	MOVE.L	#SYSNAM,FNAMPN(A3)	;load string pointer
	MOVE.L	#BIOS_CODE,LOADPN(A3)	;LOAD BIOS ADDRS
	BSR	FINDFIL
	BNE.S	ABORT		;go debugger
	LEA	MSG1,A0
	JSR	TERMTEXT
	JSR	TERMCRLF
	BSR	LOADFIL
	BNE.S	ABORT
;	
;**************** SET UP DONE, START A PROGRAM ***********************
	JMP	BIOS_CODE	;START BIOS
;
;**************** COULD NOT LOAD SYSTEM ******************************
ABORT	LEA	MSG2,A0
	JSR	TERMTEXT
	JSR	TERMCRLF
	JMP	DEBUG		;EXIT TO DEBUGGER
	RTS
;
********************* SYSTEM LOAD ROUTINES *************************
;------------------------------- FIND FILENAME IN DIRECTORY
FINDFIL	
	MOVEQ	#15,D0
FIND20	MOVEQ	#10,D1
	MOVEA.L	DIRPN(A3),A0
	MOVEA.L	FNAMPN(A3),A1
FIND30	CMPM.B	(A0)+,(A1)+	;COMPARE DIR ENTRY TO FILE NAME
	DBNE	D1,FIND30
	BNE.S	FIND40
	RTS			;RETURN TRUE IF EQUAL
FIND40	ADDI.L	#32,DIRPN(A3)
	DBRA	D0,FIND20		;ENDFOR
	MOVEQ	#1,D0
	RTS			;RETURN FALSE IF NOT FOUND
;------------------------------- LOAD BINARY FILE INTO MEMORY
LOADFIL	
	MOVEA.L	DIRPN(A3),A0	;GET DIR.START
	ADDA.L	#26,A0
	BSR	LDINTELWORD
	BSR	BLKTOREC	;CONVERT START BLOCK TO START RECORD
	MOVE.L	D0,RECORD(A3)
	MOVEA.L	DIRPN(A3),A0	;GET DIR.SIZE
	ADDA.L	#28,A0
	BSR	LDINTELLONG
	ADDI.L	#511,D0		;CALC NUMBER OF RECORDS TO LOAD
	MOVEQ	#9,D1
	LSR.L	D1,D0
	MOVE.L	D0,RECCNT(A3)	;FOR ALL RECORDS IN FILE
LOAD20	BSR	TRANSFORM	;PUSH NEXT SECTOR/BLOCK
	
	MOVE.W	SECTOR(A3),-(A7) ;PUSH sector number
	MOVEA.L	LOADPN(A3),A0
	MOVE.L	A0,-(A7)	;PUSH location on stack
	MOVEA.W	#512,A0		;one sector load
	MOVE.L	A0,-(A7)	;PUSH sector length
	MOVE.W	DRIVE(A3),-(A7)	;PUSH drive number
	JSR	FDREAD

	ADDI.L	#512,LOADPN(A3)	;ADVANCE POINTER
	BSR	NEXTREC		;CALC NEXT RECORD NUMBER USING FAT
	SUBQ.L	#1,RECCNT(A3)
	BNE.S	LOAD20		;ENDFOR
	RTS
;------------------------------- CALC NEXT RECORD USING FAT
NEXTREC	MOVE.L	RECORD(A3),D0
	BTST.L	#0,D0		;IF ODD( RECORD ) THEN
	BEQ.S	NXRC10
	BSR	RECTOBLK	;RECORD=BLKTOREC( NEXTBLK( RECTOBLK( RECORD)))
	BSR	NEXTBLK
	BSR	BLKTOREC
	BRA.S	NXRC20
NXRC10	ADDQ.L	#1,D0		;ELSE RECORD = RECORD +1
NXRC20	MOVE.L	D0,RECORD(A3)
	RTS
;------------------------------- CONVERT RECORD NUMBER TO FAT INDEX
RECTOBLK
	SUBI.L	#12,D0
	LSR.L	#1,D0
	ADDQ.L	#2,D0
	RTS
;------------------------------- CONVERT FAT INDEX TO RECORD NUMBER
BLKTOREC
	SUBQ.L	#2,D0
	LSL.L	#1,D0
	ADDI.L	#12,D0
	RTS
;------------------------------- GET NEXT BLOCK IN FAT CHAIN
NEXTBLK	MOVE.L	D0,D1
	ADD.L	D1,D0	;TABLEPOINTER=BLOCK*3/2+FATBUF
	ADD.L	D1,D0
	LSR.L	#1,D0
	LEA	BOOT_FAT,A0
	ADDA.L	D0,A0
	BSR	LDINTELWORD
	BTST.L	#0,D1	;IF PREVIOUS WAS ODD
	BEQ.S	NXBL10
	LSR.L	#4,D0	;THEN SHIFT OUT LOW NIBBLE
	RTS
NXBL10	ANDI.W	#0FFFH,D0;ELSE MASK OFF HIGH NIBBLE
	RTS
;------------------------------- LOAD A WORD STORED IN INTEL FORMAT
LDINTELWORD
	MOVEQ	#0,D0
	MOVE.B	1(A0),D0
	LSL.L	#8,D0
	MOVE.B	(A0),D0
	RTS
;------------------------------- LOAD A LONG STORED IN INTEL FORMAT
LDINTELLONG
	MOVEQ	#0,D0
	ADDQ.L	#4,A0
	MOVE.B	-(A0),D0
	LSL.L	#8,D0
	MOVE.B	-(A0),D0
	LSL.L	#8,D0
	MOVE.B	-(A0),D0
	LSL.L	#8,D0
	MOVE.B	-(A0),D0
	RTS

;--------------- CONVERT LOGICAL RECORD TO SECTOR/SAGE BLOCK
TRANSFORM
	MOVE.L	RECORD(A3),D0
	MOVE.W	D0,SECTOR(A3)
	RTS
;

**************** RUN TIME CONSTANTS *********************************
SYSNAM	DC.B	"SYSTEM  BIO",0
;
INITMSG	DC.B	"HTPL-SAGE BOOTSTRAP",0
MSG1	DC.B	"LOADING BIOS",0
MSG2	DC.B	"READ ERROR",0
;
********************* VARIABLES ***************************
	ORG	BOOT_VAR	
;
VARS	EQU	$
;
RECORD	EQU	$-VARS
	DS.L	1	;LOGICAL RECORD TO READ/WRITE
FNAMPN	EQU	$-VARS
	DS.L	1	;LOAD FILENAME
LOADPN	EQU	$-VARS
	DS.L	1	;LOAD ADDRESS
DIRPN	EQU	$-VARS
	DS.L	1	;DIRECTORY ENTRY
RECCNT	EQU	$-VARS
	DS.L	1	;LOAD RECORD COUNTER
RTNADD  EQU	$-VARS	
	DS.L	1	;RETRUN ADDRESS
DRIVE	EQU	$-VARS
	DS.L	1
SECTOR	EQU	$-VARS
	DS.L	1

	END
	