;*****************************************************************
;	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 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 REGISTER
;
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) AN EVEN PAGE BOUNDARY ADDRESS
	POP	H		;GET THE SAVED CCP STACK POINTER
	SPHL			;RESET FOR GOING TO MOVED PROGRAM
	XCHG			;GET TRANSFER ADDRESS FROM (DE)
	PCHL			;OFF TO THE MOVED CODE AREA
;
	END
;
;
;+++...END OF FILE
