;       PRLOADER.ASM VERSION 1.0
;       11/3/80 BY RON FOWLER, WESTLAND, MICHIGAN
;
;
;       THIS PROGRAM IS A LOADER DESIGNED TO BE
;       ADDED TO A PROGRAM REQUIRING RELOCATION.
;       THE PROGRAM MUST BE OF TYPE PRL, AND THIS
;       CODE (IN HEX FORM) MUST BE ADDED TO IT
;       VIA DDT OR SID.  THE PROCEDURE IS:
;
;               A>DDT <FILENAME>.PRL
;               *IPRLOADER.HEX
;               *R
;               *^C
;               A>SAVE XX <FILENAME>.COM
;
;       THE FILE SIZE PARAMETER LOCATED IN THIS
;       CODE AT LOCATION 101H IS FILLED IN BY
;       GENMOD.COM IN THE PRL FILE.  THE FILE
;       RELOCATION ADDRESS AT 104H IS FILLED IN
;       BY THE USER, AND IF LEFT 0, WILL CAUSE
;       THE FILE TO LOAD UNDER THE CCP.  IF SET
;       TO 0001H, THE FILE WILL LOAD UNDER THE
;       BDOS, OVERLAYING THE CCP.
;
BDOS    EQU     5
BYE     EQU     1       ;THIS SPECIALLY FOR BYE PGM
CPM2    EQU     1       ;THIS NEEDED ONLY FOR BYE
COMUSR  EQU     15      ;THIS TOO...USED WITH RBBS
;
;
       ORG     100H
;
       DB      01H     ;LXI B
       DS      2       ;GENMOD FILLS IN PGM SIZE HERE
       LXI     H,0     ;PGM RUN ADRS, IF 0 OR 1 THEN IN TPA
       LXI     SP,200H ;MAKE SURE SPACE AVAILABLE WHEN MODIFYING THIS PGM
       LXI     D,200H  ;ADRS OF PRL STUFF
       MOV     A,H     ;IF H IS NZ, THEN WE HAVE..
       ORA     A       ;..ADRS TO RELOCATE TO
       JNZ     MOVE
       MOV     A,L     ;NO REL ADRS SUPPLIED, CHECK OPTIONS
       LHLD    6       ;TOPMEM FOR LATER
       ORA     A       ;IF ADRS WAS NOT ZERO..
       MOV     A,H
       JNZ     OVLCCP  ;..THEN FORGET THE CCP
       SUI     8       ;..ELSE SAVE SPACE FOR IT
OVLCCP: DCR     A
       SUB     B       ;SUBTRACT OUR PROGRAM SIZE
       MOV     H,A     ;SAVE IN HL
;
;       AT THIS POINT, ADD IN ANY NECESSARY
;       CODE TO TEST L=6...THIS MAY BE NECESSARY
;       TO DETERMINE IF THIS CODE IS ALREADY IN
;       MEMORY
;
       MVI     L,0     ;RELOC ADRS MUST BE ON PAGE BOUNDARY
MOVE:   XCHG            ;SHIFT GEARS
       PUSH    B       ;SAVE COUNT
       PUSH    D       ;AND REL ADRS
MOVLOP: MOV     A,B     ;CHECK COUNT FOR ZERO
       ORA     C
       JZ      RELOC   ;EXIT LOOP WHEN COUNT=0
       DCX     B       ;COUNTDOWN
       MOV     A,M     ;PICK UP
       STAX    D       ;PUT DOWN
       INX     D       ;BUMP POINTERS
       INX     H
       JMP     MOVLOP  ;AND LOOP
;
;       THE CODE HAS BEEN MOVED, NOW RELOCATE
;       IT AT IT'S NEW LOCATION.
;
RELOC:  POP     D       ;GET RELOC ADRS
       POP     B       ;GET BACK COUNT
       PUSH    H       ;SAVE BITMAP POINTER
       MOV     H,D     ;BASE PAGE ADDRESS IN H
RLOOP:  MOV     A,B     ;TEST COUNT FOR ZERO
       ORA     C
       JZ      FINISH  ;EXIT LOOP WHEN COUNT=0
       DCX     B       ;BUMPDOWN COUNT
       MOV     A,E     ;CHECK BYTE BOUNDARY..
       ANI     7       ;..OF BIT MAP
       JNZ     NOT8    ;SKIP IF NOT OUT OF BITS
       XTHL            ;ELSE GET BITMAP POINTER
       MOV     A,M     ;GET NEXT BYTE FROM BITMAP
       INX     H       ;POINT AHEAD
       XTHL            ;RESTORE THINGS
       MOV     L,A     ;BITMAP BYTE GOES IN L
NOT8:   MOV     A,L     ;TEST NEXT BIT
       RAL
       MOV     L,A     ;PUT SHIFTED BIT BACK FOR NXT TIME
       JNC     NOTREL  ;BITS THAT ARE ZERO ARE NOT RELOC'ED
       LDAX    D       ;ELSE GET NEXT BYTE INTO ACCUMULATOR
       ADD     H       ;ADD BASE PAGE
       STAX    D       ;STORE IT BACK RELOCATED
NOTREL: INX     D       ;BUMP PROGRAM POINTER
       JMP     RLOOP   ;THEN LOOP
FINISH: POP     D
       MVI     L,0
       PUSH    H       ;SAVE ADRS TO JMP TO FOR LATER
;
;       INSERT ANY CODE NEEDED BEFORE BRANCH
;       TO PROGRAM AT THIS POINT.
;
       IF      BYE     ;DO THIS STUFF FOR BYE PROGRAM
       MVI     A,0C3H  ;CLEAR ANY TRAPS SO SYSOP..
       STA     0       ;CAN USER "BYE /A"
       XRA     A       ;NEXT WARMBOOT TO USR0/DRV A
       STA     4
       MVI     C,14    ;MAKE DRIVE A DEFAULT
       MOV     E,A     ;LOG-IN DRIVE CP/M FUNCTION
       CALL    BDOS
       ENDIF           ;OF (IF BYE)
;
       IF      CPM2 AND BYE ;SET USER 0
       MVI     C,32    ;GET/SET USR CP/M FUNCTION
       MVI     E,COMUSR
       CALL    BDOS
       ENDIF           ;OF (IF CPM2 AND BYE)
;
       RET             ;TO ADRS PUSH'ED ABOVE