hunk_unit	=	$3e7
hunk_name	=	$3e8
hunk_code	=	$3e9
hunk_data	=	$3ea
hunk_bss	=	$3eb
hunk_reloc32	=	$3ec
hunk_reloc16	=	$3ed
hunk_reloc8	=	$3ee
hunk_ext	=	$3ef
hunk_symbol	=	$3f0
hunk_debug	=	$3f1
hunk_end	=	$3f2
hunk_header	=	$3f3
hunk_lsdheader	=	"LSD!"
hunk_overlay	=	$3f5
hunk_break	=	$3f6

		lea	file(pc),a0		; File to Relocate
		bsr	_LVOHunkLength		; get size requirements...
						; d0=org`ed size
		lea	file(pc),a0
		lea	buffer,a1
		bsr.b	_LVOHunkRelocate	; relocate file...
		bne.s	RelocFailed		; did relocation fail?

		jsr	(a0)			; run relocated program.

RelocFailed:	rts


_LVOHunkLength:	suba.l	a1,a1			; Get length of relocated...
_LVOHunkRelocate:
		move.l	a1,-(sp)		;preserve dest adr
		move.l	a1,a4			; erase a1
		move.l	a1,a3			; erase a3
		move.l	(a0)+,d0		; read longword from file
		cmp.l	#hunk_header,d0		; must start with a hunk_header
		beq.s	hunkname		; if not we`ve got problems!
		cmp.l	#hunk_lsdheader,d0	; must start with a hunk_header
		bne.w	relocerror		; if not we`ve got problems!
hunkname	move.l	(a0)+,d0		; if its named, skip name
		beq.s	hunkok			; if 0 its alright!
		add.l	d0,d0			; x2
		add.l	d0,d0			; x4 (convert BCPL pointer)
		add.l	d0,a0			; add to ptr
		bra.s	hunkname		; deal with hunk name...
 
hunkok		move.l	(a0)+,d7		; read no. hunks from file
		move.l	d7,d6			; d6=copy of no.hunks...
		add.l	d7,d7
		add.l	d7,d7
		add.l	d7,d7			; 2 long words per hunk
		sub.l	d7,sp
		addq.w	#8,a0			; skip first/last hunk nos
		move.l	sp,a1
		move.l	sp,a5
hunksetuplp	move.l	(a0)+,d0		; get hunk length
		add.l	d0,d0
		add.l	d0,d0			; x4 Get address from BCPL ptr
		move.l	d0,(a1)+		; length
		addq.l	#8,a3			; add segment header
		move.l	a3,(a1)+		; ptr
		add.l	d0,a3
		subq.l	#1,d6
		bne.s	hunksetuplp

		cmpa.l	#0,a4			; are we going to reloc or get length ?
		bne.s	hunkdoit		; getlength - hunklen in header (.l)
		move.l	d7,d0			; zero count+8 bytes per hunk
hunksumlp	add.l	(sp)+,d0		; add lengths etc.
		addq.l	#4,sp			; recover stack at same time!
		subq.l	#8,d7
		bne.s	hunksumlp
		bra.w	relocok

hunkdoit	move.l	d7,d6
hunkproclp	move.l	(a0)+,d0		; read hunk type
		bsr.s	idproc_hunk
		bne.s	hunkproclp
		bra.w	relocdone

idproc_hunk	cmp.w	#hunk_unit,d0
		beq.w	hunkskip
		cmp.w	#hunk_name,d0
		beq.w	hunkskip
		cmp.w	#hunk_code,d0
		beq.b	hunkcode
		cmp.w	#hunk_data,d0
		beq.b	hunkcode
		cmp.w	#hunk_bss,d0
		beq.b	hunkbss
		cmp.w	#hunk_reloc32,d0
		beq.b	hunkreloc
		cmp.w	#hunk_symbol,d0	; implemented 6/2/92
		beq.b	hunksymb
		cmp.w	#hunk_debug,d0	; 6/2/92
		beq.b	hunkskip
		cmp.w	#hunk_end,d0	; eof
		beq.w	hunkend	
		bra.b	hunkfin	 	; id has failed! must be ext/16/8/reloc16
					; or something not in exe files!
hunkcode	move.l	(a0)+,d0		; get length
		move.l	(a5),d1			; get length ii
		move.l	4(a5),a6
hunkcodelp	move.l	(a0)+,(a6)+		; copy though
		subq.l	#4,d1
		subq.l	#1,d0
		bne.s	hunkcodelp
		tst.l	d1			; if length mismatch, wipe rest
		beq.s	hunkcodeok
hunkcodelp2	clr.l	(a6)+
		subq.l	#4,d1
		bne.s	hunkcodelp2
hunkcodeok	moveq.l	#1,d0
		rts	
 
hunkreloc	move.l	(a0)+,d0		; get no of relocs
		beq.s	hunkrelocfin
		move.l	(a0)+,d1		; get hunk
		add.l	d1,d1
		add.l	d1,d1
		add.l	d1,d1			; x8
		move.l	8(sp,d1.l),d3		; get hunk base
		move.l	4(a5),a6
hunreloclp	move.l	(a0)+,d2		; get offset
		add.l	d3,0(a6,d2.l)
		subq.l	#1,d0
		bne.s	hunreloclp
		bra.s	hunkreloc
hunkrelocfin	moveq.l	#1,d0
		rts	

hunkbss		move.l	(a0)+,d0		; get length
		move.l	4(a5),a6		; get start

		move.l	d1,-(sp)		; save d1 to stack
		moveq	#0,d1			; erase d1
hunkbsslp	move.l	d1,(a6)+		; wipe d0 longwords using d1
		subq.l	#1,d0			; decrease counter
		bne.s	hunkbsslp		; is it zero?

		moveq.l	#1,d0			; set d0 as 1
		move.l	(sp)+,d1		; restore d1 from stack
		rts	
 
hunkskip	move.l	(a0)+,d0		; get length, add to file ptr
		add.l	d0,d0
		add.l	d0,d0			; get Address from BCPL ptr
		add.l	d0,a0
		moveq.l	#1,d0
		rts	

hunksymb	move.l	(a0)+,d0		; flush symbol name
		add.l	d0,d0
		add.l	d0,d0			; get Address from BCPL ptr
		lea	(a0,d0.l),a0
		tst.l	d0
		beq.s	donesym
		addq.l	#4,a0			; flush symbol value
		bra.s	hunksymb
donesym		moveq	#1,d0
		rts		

hunkfin		moveq.l	#0,d0
		rts	
hunkend		addq.w	#8,a5
		subq.l	#8,d6
		rts	
relocdone
fixsegs		move.l	(sp)+,d0	; length
		move.l	(sp)+,a0	; ptr
		addq.l	#8,d0		; length incldues header info
		move.l	d0,-8(a0)	; punch out segment length
		move.l	4(sp),d1	; next ptr	
		subq.l	#4,d1		; ptrs point to each other not actual code/data
		lsr.l	#2,d1		; make bcpl
		move.l	d1,-4(a0)	; put in next ptr
		subq.l	#8,d7		; d7=8*numsegs
		bne.s	fixsegs

		clr.l	-4(a0)		; kill last 'next ptr',crap from stack
		moveq	#0,d0		; erase d0
		bra.s	relocok 
 
relocerror	moveq	#-1,d0
relocok		move.l	(sp)+,a0	;get dest, put in a0
		addq.l	#8,a0		;a0=jmp address
		tst.l	d0		; did it fail?
		rts	

file		incbin	'df0:1'
buffer		dcb.b	338722,0
