;...................................
;: (c) 1993 Rebellion Software Ltd :
;: Hand coded by R.C.Dibley - 1993 :
;:.................................:
; simple relocater allowing any amount of data to be relocated - uses extended dbra technology !

.text

Rel::	addq.l	#3,d0			; prevent rounding loss
	asr.l	#2,d0			; cut down to longs
	bra.b	.de

.ret:	swap	d0
.rel:	move.l	(a1)+,(a0)+
.de:	dbra	d0,.rel
	swap	d0	; bring upper word down
	dbra	d0,.ret
	rts

Data_reloc::
	movea.l	#End_of_text+8,a1		; where data segment will be placed in ROM
	move.l	#End_of_data+8,d0
	movea.l	#Blob1,a0
	sub.l	a0,d0
	bsr	Rel
;	tst.b	sound1st			; see if first time round (for transferring out)
;	bne.b	exit				; and if it isn't don't bother with CRC check
;	bsr	CRCtest
exit:	rts


RAM_to_ROM::
	movea.l	#End_of_text+8,a1		; where data segment will be placed in ROM
	move.l	#End_of_data+8,d0
	movea.l	#Blob1,a0
	sub.l	a0,d0
	tst.l	-8(a1)				; check the end of data marker - zero implies not yet relocated into ROM
	bne.b	.inrom
	exg	a1,a0				; make it a RAM to ROM write
	bsr	Rel				; perform relocate
	bsr	CRCtest				; and generate CRC's
.inrom:	rts


; additional relocation routines - relocate and patchup the two sections of 3d data
; data has to be moved from OBJECTS1(2) up to OBJECTS2(E) and moved to the point End_of_data+8
; patch backs occur in the range Zlim1(2) to Zlim2(E) and only apply to addresses in the right range
; it must be checked that the total doesn't go past Genstr because thats where the 3d world is built

; this must in fact be split, so that the patch-up is performed on all relevant values before they are
; put into the cartridge space.  This way, the data can be relocated anytime without fault, otherwise 
; every attempt to relocate would have to be prefixed with a complete re-write of the data segment !


; register allocations - input just requires the set number in d0
; during course of routine, uses are :
; d0 = start address
; d1 = target address
; d2 = data length 		these chosen because using blitmove to relocate
; during patch back :
; d1 = start address for range checking
; d2 = high address for range checking
; d3 = offset amount
; a0 = scan address
; d0 = new loop counter

Request_3d::				; relocates 3d block n(d0) to the end of the data segment
	movem.l	d0-d2/a2,-(sp)
	subq.w	#1,d0			; so set 1 becomes 0
	asl.w	#4,d0			; * 16 = 4 longs
	lea	Block_pointers-*-2(PC),a2
	adda.w	d0,a2
	move.l	(a2)+,d0		; read source address
	move.l	(a2)+,d2		; read end address
	sub.l	d0,d2
	move.l	#End_of_data+8,d1
	bsr	Long_blit

	movem.l	(sp)+,d0-d2/a2
	rts

Patch_3d::				; one off pre-pass on data to ensure that pointers to data compiled 
	movem.l	d0-d4/a0-a2,-(sp)	; in _ROM_ point to where the _RAM_ version will be

	lea	Block_pointers-*-2(PC),a2	; first time round just start at first item in list
						; afterwards loop back unless end marker (0) hit
.start:	move.l	(a2)+,d1		; read source address - low limit
	beq.b	.exit
	move.l	(a2)+,d2		; read end address - high limit

	move.l	#End_of_data+8,d3	; address the data is moved to
	movea.l	(a2)+,a0		; data input [patchup] area
	move.l	(a2)+,d0		; end of area
	sub.l	a0,d0			; length
	asr.l	#2,d0			; scale down
	sub.l	d1,d3			; get adjustment to apply - add this to each entry to give right value
	bra.b	.le

.lp:	move.l	(a0)+,d4
	beq.b	.le
	cmp.l	d4,d1			; check against lower limit
	bgt.b	.le			; if lower limit is greater than the value being considered ...
	cmp.l	d4,d2			; check against upper limit
	blt.b	.le			; if higher limit is lower than the value being tested ...
	add.l	d3,-4(a0)
.le:	dbra	d0,.lp

	bra	.start
.exit:	move.w	#$4e75,Patch_3d		; trick to disable routine after one use !!!!!! this writes RTS into first word
	movem.l	(sp)+,d0-d4/a0-a2
	rts

Block_pointers:
	dc.l	OBJECTS1,OBJECTS2,Zlim1,Zlim2
	dc.l	OBJECTS2,OBJECTSE,Zlim2,ZlimE
	dc.l	OBJECTS1,OBJECTS2,car_anim,end_car_anims
	dc.l	0

; note on car_anim ...
; changing the data here just allows the RAM copy to be used and modified, as it was using ROM
; however it should be noted that the ROM information block is still used because even if
; an attempt was made to fix it, the value has its high bit set !
; Also, the data for this is in the tgen data blocks (ie in tdef.s) and so contains values
; normally in the limz area, which are then cross-fixed

Code_reloc::
	move.l	#$802000,d0
	move.l	#TextEnd,d2
	sub.l	d0,d2
	move.l	#code_space,d1
	bsr	Long_blit
	rts
