	Opt	C-
* AmigaDos Fileloader V2.0 - Written by Motive/Dimension-X
* for inclusion in Deadlock Issue 6
*
* This boot-block code, will relocate itself to a high-part of memory 
* and then load the file that has been specified. 
* 
* This Routine is no-where near as effective as it could be but it
* does the job, below are a list of functions which 
* 
*----------------------------------/X\acros----------------------------------


Highmemory = $7f000		; Address to relocate to

td_motor_off	macro
	move.w  #$0009,$1c(a1)
	move.l  #$00000000,$24(a1)
	move.l	4.w,a6
	jsr     -$1c8(a6)
	endm

td_read	macro
	move.l  #\1,$28(a1)			;address to read to
	move.l  #\2*512,$2c(a1)			;block offset
	move.l  #\3*512,$24(a1)			;no of blocks
	move.l	4.w,a6
	jsr     -$1c8(a6)
	endm

bootdos	macro
	dc.b	"DOS",0
	dc.l	0,$370
	endm
bootndos	macro
	dc.b	"NDOS"
	dc.l	0,$370
	endm

*----------------------------------/X\acros----------------------------------

bootblockstart:
	bootdos
	lea	diskio_addr(pc),a0	;store trackdisk io structure
	move.l	a1,(a0)	

	lea	$dff000,a5
 	move.w	#$180,$96(a5)		;disable copper&bitplane dma
	move.w	#$0,$180(a5)		

	;lea	$7fff0,a7

	lea	RelocateStart(pc),a0	
	lea	HighMemory,a1		;high-memory

	move.w	#Bootsize-1,d0		;size of code to copy
copyloop:
	move.b	(a0)+,(a1)+
	dbra	d0,copyloop
	
	jmp	HighMemory
	

RelocateStart:
	lea	filename(pc),a0		;filename
	lea	$40000,a3		;address to load to
	bsr	load_file
	tst.l	d0
	bmi	file_doesnt_exist	;


;----------------------------------------
;call your code from here!
	lea	$40020,a0
	move.l	a0,$80.w
	trap	#0
	


;----------------------------------------
	
file_doesnt_exist:
	moveq.l	#-1,d0			;this should never occur
	rts				;unless you have forgot to put you
					;files on disk





filename_address	dc.l	0
load_file:	
	bsr	calc_hash
	move.l	d0,d1
	move.l	d0,-(a7)
get_root_block:
	move.l	diskio_addr(pc),a1	;retrieve io request structure

	lea	buffer(pc),a0
	move.l  a0,$28(a1)
	move.l  #880*512,$2c(a1)	;block 880 (track 40)
	move.l  #1*512,$24(a1)		;1 block to read
	move.l	4.w,a6
	jsr     -$1c8(a6)		;do diskio request
	
	move.l	diskio_addr(pc),a1
	tst.b	32(a1)
	beq.s	no_root_error
	bra.s	get_root_block		;continous loop !?!?
no_root_error:
	move.l	(a7)+,d0
	lea	buffer+(6*4)(pc),a0	;find start of hash table
	move.l	(a0,d0.l),d0		;get pointer to file header block
	tst.l	d0			;if zero then no such file!
	beq	no_file			
	move.l	d0,d2
get_fh_block
	moveq.l	#1,d1
	lea	buffer(pc),a0		;address to read fh block
	bsr	read_blocks		;read file header block
	tst.b	d0
	beq.s	no_fh_error		;errro attempting to read block
	
	move.l	d2,d0
	bra.s	get_fh_block
no_fh_error:


check_file_header:
	lea	buffer(pc),a0
	add.l	#(108*4)+1,a0		;locate filename in fh block
	move.l	filename_address(pc),a5
	move.l	a5,a2	;filename
check_filename_loop:			;compare filename & filename in fh block
	move.b	(a0)+,d2
	bsr	upper			;convert to upper case
	move.b	d2,d3
	move.b	(a2)+,d2
	bsr	upper			;convert to upper case
	move.b	d2,d4
	tst.b	d4
	beq	name_complete
	cmp.b	d3,d4
	bne.s	wrong_filename
	bra.s	check_filename_loop
wrong_filename:				;if wrong file then try next
	lea	buffer(pc),a0		;file in the hash chain

	move.l	124*4(a0),d0		;next in hash chain
	move.l	#1,d1			;block_len
	tst.l	d0			;if zero then end of hash chain
	beq.s	no_file	
	move.l	d0,d2
get_fh_next:
	lea	buffer(pc),a0
	bsr	read_blocks		;read next fh in chain
	tst.b	d0
	beq.s	no_fhchain_error
	
	move.l	d2,d0
	
	bra.s	get_fh_next

no_fhchain_error:

	bra.s	check_file_header
name_complete:

load_data_loop:
	lea	buffer(pc),a0	;pointer to data-block
	move.l	4*4(a0),d0
	tst.l	d0
	beq.s	file_end	;if zero then no more blocks to read
	move.l	d0,d2
get_data_block
	moveq.l	#1,d1
	lea	buffer(pc),a0
	bsr	read_blocks	;read data block
	tst.b	d0
	beq.s	no_data_error
	
	
	move.l	d2,d0
	bra.s	get_data_block
no_data_error

	bsr	check_checksum	
	tst.l	d0
	bpl	block_ok

reset_drive:	
	bra	load_data_loop
	

block_ok:
	lea	buffer(pc),a0
	move.l	load_address(pc),a2
	move.l	3*4(a0),d0	;size of data block
	lea	6*4(a0),a0	;pointer to start of data
copy_data_loop:
	move.b	(a0)+,(a2)+	;copy block read in to load-address
	subq.l	#1,d0
	bne.s	copy_data_loop

	lea	load_address(pc),a0
	move.l	a2,(a0)		;store load-address
	bra.s	load_data_loop	
file_end:
	td_motor_off
	moveq.l	#1,d0		;no error
	rts
no_file:
	
	td_motor_off
	moveq.l	#-1,d0		;file error
	rts

upper:	cmp.b	#'a',d2
	blt.s	not_lower
	cmp.b	#'z',d2
	bgt.s	not_lower
	sub.b	#$20,d2		
not_lower
	rts

calc_hash:
	movem.l	d0-d7/a0-a6,-(a7)
	lea	load_address(pc),a2
	move.l	a3,(a2)
	move.l	a0,a1
	moveq.l	#0,d0		;name length
	move.l	a0,a5
	lea	filename_address(pc),a4
	move.l	a5,(a4)

next_character:
	tst.b	(a1)+
	bne.s	next_character
	sub.l	a0,a1
	subq.l	#1,a1
	move.l	a1,d0
	move.l	a0,a1
	move.l	d0,d1
	subq.l	#1,d1
hash_char
	moveq.l	#0,d2
	
	mulu	#13,d0
	move.b	(a0)+,d2	;next character
	bsr.s	upper		;convert to upper-case
	add.w	d2,d0
	and.w	#$7ff,d0
	dbra	d1,hash_char
	divu	#72,d0
	swap	d0		;remainder (modulo)
	lsl.w	#2,d0
	and.l	#$ffff,d0
	move.l	d0,(a7)
	movem.l	(a7)+,d0-d7/a0-a6
	rts	


load_address	dc.l	0	
;	td_motor_off
;	td_read	address,sector_offset,sector_len

read_blocks:
	movem.l	d0-d7/a0-a6,-(a7)
	move.l	diskio_addr(pc),a1	;retrieve io request structure
	move.l  a0,$28(a1)		;address to read to
	mulu	#512,d0			;block offset * 512
	mulu	#512,d1			;block length * 512
	move.l  d0,$2c(a1)		
	move.l 	d1,$24(a1)
	move.l	4.w,a6
	jsr     -$1c8(a6)		;Do DiskIO
	move.l	diskio_addr(pc),a1
	moveq.l	#0,d0
	move.b	32(a1),d0		;get possible error flags (if any)
	move.l	d0,(a7)
	movem.l	(a7)+,d0-d7/a0-a6
	rts

Check_checksum:
	movem.l	d1-d7/a0-a6,-(a7)
	Lea	Buffer,a0
	Move.l	20(a0),d1
	Move.l	#0,20(a0)		
	MOveq.l	#0,d0
	Move.w	#$7f,d0
.Checksum_loop:
	Add.l	(a0)+,d1
	Dbra	d0,.Checksum_loop
	Tst.l	d1
	Beq.s	.Checksum_Ok
.Checksum_error:
	Moveq.l	#-1,d0
	Movem.l	(a7)+,d1-d7/a0-a6
	Rts
.Checksum_Ok:
	Moveq.l	#1,d0	;No_error
	Movem.l	(a7)+,d1-d7/a0-a6
	rts

	

diskio_addr	dc.l	0

filename:	dc.b	"loader.exe",0

buffer:					;start address to load blocks to
bootsize=*-RelocateStart		;Length of Boot Code

	End
