10 REM > LibMax/s 0.11
   20 REM Library Maximiser
   30 REM NB: Currently only works on MOS 3 onwards!
   40 REM ??-???-1997 v0.02 JJR: Initial version, works via direct entry
   50 REM 20-Feb-1999 v0.10 JGH: Rewritten to trap errors properly
   60 REM 28-Feb-1999 v0.11 JGH: Module-compatible relocation table
   70 :
   80 IFHIMEM<TOP:MODE&87
   90 REM EXTENDED VECTORS START AT &0D9F
  100 DIM mcode% 1024:ver$="0.11 (28 Feb 1999)"
  110 OSNEWL=&FFE7:OSWRCH=&FFEE
  120 VectorTable=&FFB6
  130 Vec0=&200: CLIV=&208
  140 XVec0=&D9F:XCLIV=&DAB
  150 lptr=&F2:  errptr=&FD
  160 :
  170 len%=0:FOR pass%=0 TO 3
  180   P%=&8100-128*(pass%AND2)
  190   O%=mcode%+len%*(pass%AND2)DIV2
  200   opt%=VALMID$("4647",pass%+1,1)
  210   [OPT opt%
  220   .RomStart
  230   BRK:EQUW RelocTable
  240   JMP RomService
  250   EQUB &82:EQUB RomCopyright-RomStart:EQUB VALver$
  260   .RomTitle    :EQUS "Library Maximiser":BRK
  270   .RomVersion  :EQUS ver$
  280   .RomCopyright:BRK:EQUS "(C)JJR,JGH":BRK
  290   :
  300   .RomHelp
  310   EQUS "  Maximises your Library capacity":EQUB 13
  320   EQUS "  *command translated to *c.command":BRK
  330   :
  340   .RomService
  350   CMP #9:BNE P%+5:JMP Service9
  360   CMP #6:BNE P%+5:JMP Service6
  370   CMP #2:BNE P%+5:JMP Service2
  380   RTS
  390   :
  400   .Service9:\ *Help
  410   LDX #0
  420   LDA (&F2),Y:CMP #13:BEQ ServHelp1
  430   CMP #ASC".":BEQ ServHelp2
  440   AND #&DF:CMP #ASC"L":BEQ ServHelp2
  450   BNE Serv9Exit
  460   .ServHelp1
  470   CLC
  480   .ServHelp2
  490   PHP:JSR OSNEWL
  500   .ServHelpLp
  510   LDA RomTitle,X:BEQ ServHelpDone
  520   JSR OSWRCH:INX:BNE ServHelpLp
  530   .ServHelpDone
  540   LDX #RomHelp-RomTitle
  550   PLP:BCS ServHelp1
  560   JSR OSNEWL
  570   .Serv9Exit
  580   LDA #9:RTS
  590   :
  600   :
  610   .Service2
  620   STX XCLIV+2                     :\ My ROM number
  630   LDA #&FF:STA CLIV+1             :\ Point to extended vector
  640   LDA #XCLIV-XVec0:STA CLIV+0
  650   LDA NewOscV+1:STA XCLIV+1       :\ RoutineHi
  660   LDA NewOscV+0:STA XCLIV+0       :\ RoutineLo
  670   LDA #2:RTS
  680   :
  690   .NewOscV
  700   EQUW NewOsc
  710   .NewOsc
  720   LDA &F4:STA &DCFF:EOR #&AA:STA &DCFE :\ Set Error Catch
  730   PHX:TSX:STX &DCFD:PLX                :\ Save stack pointer
  740   JSR DoOscli                          :\ Try to do the command
  750   .ErrorUntrapped
  760   LDA #0:STA &DCFF:STA &DCFE           :\ Clear Error Catch Flag
  770   LDA #6:RTS                           :\ Exit from Service 6
  780   :
  790   .DoOscli
  800   CLC:LDA #CLIV-Vec0:ADC VectorTable+1:STA &101
  810   LDA #0:ADC VectorTable+2:STA &102    :\ Get pointer to address of real OSCLI
  820   LDA #&6C:STA &100:JMP &100
  830   :
  840   .Service6                            :\ An error has occured
  850   LDA &DCFF:EOR &DCFE:CMP #&AA:BNE ErrorUntrapped
  860   LDY #0:LDA (errptr),Y:CMP #254:BNE ErrorUntrapped
  870   LDX &DCFD:TXS:PLX                    :\ Restore stack pointer
  880   LDY #0
  890   .ErrorRealign
  900   LDA (lptr),Y:STA &DC00,Y
  910   INY:CMP #13:BNE ErrorRealign         :\ Ensure string starts at &DC00
  920   LDX #&FD
  930   .ErrorMoveUp
  940   LDA &DBFF,X:STA &DC02,X
  950   DEX:BNE ErrorMoveUp                  :\ Move up 3 for extra characters
  960   STA &DC01:LDA #ASC".":STA &DC02
  970   LDA #ASC"/":STA &DC00                :\ Add '/x.' to start
  980   JSR ErrorUntrapped                   :\ Untrap errors
  990   LDX #0:LDY #&DC:JMP DoOscli          :\ Try command again
 1000   :
 1010   .RelocTable
 1020   ]
 1030   len%=RelocTable-RomStart
 1040 NEXT
 1050 PROCMakeRelocTable
 1060 PRINT"*Save LibMax "+STR$~(mcode%+len%)+" "+STR$~O%+" 0 FFFBBC00"
 1070 END
 1080 :
 1090 DEFPROCMakeRelocTable
 1100 base80%=mcode%+len%:base81%=mcode%:byte%=0:count%=0:off%=0:REPEAT
 1110   byte80%=base80%?off%:byte81%=base81%?off%:IF off%>=len%:byte80%=&80:byte81%=&80
 1120   IF ((byte81%-byte80%) AND &FE)<>0 THEN PRINT "ERROR: Offset by more than one page at &";~&8000+off%
 1130   IF (byte80% AND &C0)=&80:byte%=byte%DIV2+128*(byte81%-byte80%):count%=count%+1
 1140   IF count%=8:?O%=byte%:O%=O%+1:byte%=0:count%=0
 1150 off%=off%+1:UNTILoff%>=len% AND count%=0
 1160 ENDPROC