I don't know about all the others, but the 18F series lets you modify FLASH at run-time. You have to first erase a block, (8-64 bytes, depending on your chip type - and you have to start at a block boundary) with the ERASECODE command. After erasure, you can write whatever you want.
I did this in several versions or "levels". This is the lowest level.

The following to allow the bootloader to run (or not) depending on a program variable. If you set PROTECT and called PatchLoader, the bootloader will not run. If in the program, you set PROTECT = 0, and run it, the bootloader will again work.

It should be noted that this was used with PBP 250a and an 18F8722 and MCLOADER.

PBP2.50a could not access the upper half of the big chips (>64K) memory using READCODE,WRITECODE or ERASECODE, so I had to modify PBPPPIC18.LIB to include a new SYSTEM variable called UPMEM. The library modification set TBLPTRU to UPMEM at the beginning of these 3 routines, and cleared UPMEM at the end (so as not to screw up PBP). By setting UPMEM to 1, I could read the upper half of memory (and by setting it to 0x30, you can set/read the configuration registers). You will see that I need to set upmem before each operation to get to that upper half of FLASH. You wouldn't have to deal with that in a smaller chip.

I have done quite a bit of this, let me know if you need any more help.


Code:
PatchLoader:

          UPMEM = 0
      
         ERASECODE $0
       
         WRITECODE $0,$EFE0          ; Change the initial jump vector
         WRITECODE $2,$F0FF          ; 0X1FFC0
 
         WRITECODE $4,$FFFF
         WRITECODE $6,$FFFF
       
         for xx = $8 TO $3E STEP 2    ; Do the rest of the block
         WRITECODE XX,$FFFF
         NEXT Xx
         
         PAUSE 100
         
         PROTECT = 1
         GOSUB PROTECT_UNPROTECT 

         RETURN


PROTECT_UNPROTECT:

         UPMEM = 1     
         ERASECODE $FFC0
        
         UPMEM = 1 
         WRITECODE $FFC0,$6B08
         UPMEM = 1 
         WRITECODE $FFC2,$0000
         UPMEM = 1 
         WRITECODE $FFC4,$0000
         UPMEM = 1 
         WRITECODE $FFC6,$0000
         UPMEM = 1 
         WRITECODE $FFC8,$3F08
         UPMEM = 1 
         WRITECODE $FFCA,$D7FB
         
       if PROTECT = 0 THEN        
             UPMEM = 1 
             WRITECODE $FFCC,$EF82
             UPMEM = 1 
             WRITECODE $FFCE,$F0FE    ; JUMP TO 1FD04
       ELSE  
             UPMEM = 1 
             WRITECODE $FFCC,$EF78
             UPMEM = 1 
             WRITECODE $FFCE,$F0FE    ; JUMP TO 1fcF0
       ENDIF
        
       FOR XX = $FFD0 TO $FFFE STEP 2
             UPMEM = 1 
             WRITECODE XX,$FFFF
       NEXT XX
         
         RETURN

REPROTECT:
         UPMEM = 1
         READCODE $FFCC,X
           IF X = $82 THEN
            HSEROUT [13,10,10,"Reprotecting Loader",13,10]
            PROTECT = 1
            GOSUB PROTECT_UNPROTECT
           ENDIF 
          RETURN  
          
GetTypeLoader:
         READCODE 0,TypeLoader
         RETURN