;****************************************************************
;	PRL FILE FORMAT RELOCATER FOR BIT MAPPED FILES
;****************************************************************
;
;
;	This small program block moves a bit map relocatable
;	file from address 0200h above this module up to a spot
;	below the CCP and then jumps to the base of the moved
;	code. The DIGITAL RESEARCH RELOCATING ASSEMBLER and the
;	companion LINKER permit the generation of the PRL file
;	format. LINK will put the code size word in to address
;	101 and 102. The code spot is intended to be 0200h with
;	the bit map immediately above the code. A one in the bit
;	map indicates the location of a moved byte that requires 
;	a relocation address offset.
;
;***************************************************************
;
;
;start point for the beginning of the mover module
;
	ORG	0100H
;
;
;GENERAL CP/M BDOS INTERFACE EQUATES.
;
BDOS	EQU	0005H		;FILE MANAGER ENTRANCE LOCATION
CODE$START EQU	0200H		;LINK 80 CODE START POINT FOR ORG 0 FILE
;
;
;START POINT OF MOVER CODE
;
	DB	01H		;INSERT HEX FILE CODE FOR LXI B,XXXX
	DS	2		;INSERT CODE SIZE FROM LINK .PRL FILE
				;WITH DDT HERE
	LXI	H,0		;GET CCP STACK FOR LATER PASSING
	DAD	SP		;TO RELOCATED PROGRAM
	LXI	SP,CODE$START	;LET STACK WORK DOWN FROM 0200H
	PUSH	H		;SAVE CCP POINTER ON OUR STACK
;
	PUSH	B		;SAVE A COPY OF CODE SIZE ON STACK
;
;
;GET BDOS PAGE ADDRESS BOUNDARY
;
	LXI	H,BDOS+2	;PAGE ADDRESS OF BDOS BASE
	MOV	A,M		;INTO (A)
	SUI	8		;DECREASE SIZE FOR CCP SIZE
				;OF EIGHT PAGES
	DCR	A		;ONE MORE TIME TO ACCOUNT FOR
				;..PARTIAL PAGE CODE SIZE
	SUB	B		;SUBTRACT CODE SIZE IN TRUNC INTETGER SIZE
;
	MOV	D,A		;(DE) = DESTINATION ADDRESS BASE
	MVI	E,0
	PUSH	D		;SAVE LOAD ADDRESS FOR LATER JUMP TO CODE
;
	LXI	H,CODE$START	;START MOVE POINTER TO (HL)
;
;
;LOOP TO MOVE CODE UP IN RAM UNDER CCP
;
MOVLOOP:
	MOV	A,B		;CHECK BYTE COUNT TO SEE IF ALL MOVED YET
	ORA	C
	JZ	MOVDONE		;EXIT LOOP IF DONE
;
	DCX	B		;DECREMENT BYTES TO MOVE COUNT
	MOV	A,M		;GET A BYTE TO MOVE
	STAX	D		;SAVE AT DESTINATION ADDRESS
	INX	D		;BUMP SOURCE DESTINATION POINTERS
	INX	H
	JMP	MOVLOOP		;GO MOVE MORE BYTES
;
;
;CODE MOVED SO SET UP TO SCAN BIT MAP
;
MOVDONE:
	POP	D		;GET BACK A COPY OF THE DESTINATION ADDR
	POP	B		;RESET (BC) TO BYTE COUNT FOR BIT MAP SCAN
	PUSH	H		;SAVE ADDRESS OF BIT MAP ON TOP OF STACK
;
	MOV	H,D		;SET (H) TO RELOCATE PAGE OFFSET
	DCR	H
;
;
;LOOP TO SCAN CODE BLOCK JUST MOVED AND TO ADD IN OFFSET OF EXECUTION
;PAGE ADDRESS ON ALL BYTES NEEDING RELOCATION.
;
RELOCLOOP:
	MOV	A,B		;CHECK BIT MAP COUNTER TO SEE IF RELOC DONE
	ORA	C
	JZ	RELOCDONE	;EXIT IF ALL BYTES CHECKED
	DCX	B		;DECREASE BYTE COUNT
	MOV	A,E		;IS (DE) ADDRESS MOD EIGHT BYTES?
	ANI	7		;IF SO WE NEED NEXT BIT MAP BYTE
	JNZ	SAMEBYTE	;STILL ON SAME BIT MAP BYTE
;
;
;GET NEXT BIT MAP BYTE VIA POINTER ON TOP OF STACK
;
	XTHL			;SAVE (HL) AND GET CURRENT MAP POINTER
	MOV	A,M		;GET MAP BYTE TO (A)
	INX	H		;INCREASE POINTER FOR NEXT TIME
	XTHL			;PUT POINTER BACK ONTO STACK
	MOV	L,A		;MAP BYTE TO HOLDING RESISTER
;
SAMEBYTE:
	MOV	A,L		;FETCH OUR CURRENT BIT MAP BYTE
	RAL			;SHIFT BIT MAP BYTE FOR NEXT BIT
	MOV	L,A		;SAVE SHIFTED ONE FOR NEXT PASS
	JNC	NOOFFSET	;SKIP OFFSET ADD IF BIT WAS NOT ONE
;
;
;GET CODE BYTE AND ADD IN OFFSET IF MAP BIT WAS 1
;
	LDAX	D		;FETCH THE DESTINATION BYTE
	ADD	H		;ADD IN OFFSET
	STAX	D		;STORE BACK AWAY
;
NOOFFSET:
	INX	D		;INCREASE THE MOVED CODE BYTE POINTER
	JMP	RELOCLOOP	;GO TO PROCESS MORE BYTES
;
;
;HERE WHEN THE RELOCATION IS DONE READY TO JUMP TO THE MOVED CODE
;REMEMBER THAT (H) HAS PAGE ADDRESS OF MOVED CODE.
;
RELOCDONE:
	POP	D		;GET BIT MAP POINTER OFF STACK
	MOV	D,H
	INR	D		;SET UP EXECUTION ADDRESS
	MVI	E,0		;MAKE (DE) AND EVEN PAGE BOUNDARY ADDRESS
	POP	H		;GET THE SAVED CCP STACK POINTER
	SPHL			;RESET FOR FOING TO MOVED PROGRAM
	XCHG			;GET TRANSFER ADDRESS FROM (DE)
	PCHL			;OFF TO THE MOVED CODE AREA
;
	END
;
;
;+++...END OF FILE
