I'm experimenting this method:

Bootloader code uses DEFINE RESET_ORG 80h and Main program uses DEFINE RESET_ORG 3000h

When the main app need to call bootloader, I disable Interrupt, then remap vectrors, then @ RESET:

Code:
	Madr=$EF40: WriteCode 0,Madr		' --> GoTo $80 at address 0	
	Madr=$F000: WriteCode 2,Madr		
	Madr=$EF42: WriteCode 4,Madr		' --> GoTo $84 at address 4
	Madr=$F000: WriteCode 6,Madr		
	Madr=$EF44: WriteCode 8,Madr		' --> GoTo $88 at address 8
	Madr=$F000: WriteCode 10,Madr
	For Madr=12 to 126 step 2			' fill 128 bytes block for PIC18 to complete WriteCode
		WriteCode Madr,$FF
	Next Madr
When the bootloader has finished, same logic above to restore vector at 3000, 3004, 3008, then @ RESET

Not sure if it is a smart solution, but in my mind it should works .....