;****************************************************************
;       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