10 REM > NullKbd/src 0.12
   20 REM Null keyboard support module
   30 REM Demonstrate building relocation table from two images in memory
   40 :
   50 PROCassem(0):CLEAR:PROCassem(2):PROCsm_table
   60 A$="*SAVE "+fname$+" "+STR$~(mcode%+M%)+" "+STR$~O%+" FFFF0000 FFFBBC00"
   70 PRINTA$;:OSCLIA$:PRINT
   80 END
   90 :
  100 DEFPROCassem(pass%)
  110 fname$="NullKBD"      :REM Name to save with
  120 DIM mcode% 1024, L% -1:REM Need enough space for two copies
  130 FOR pass%=pass% TO pass%+1
  140   opt%=FNsm_pass(pass%)+8+16
  150   [OPT opt%
  160   .RomStart
  170   BRK:EQUW RelocTable
  180   JMP Service
  190   EQUB &82:EQUB Copyright-RomStart
  200   EQUB &00:EQUS "NullKeyboard"
  210   EQUB &00:EQUS "0.12 (01 Aug 1998)"
  220   .Copyright
  230   EQUB &00:EQUS "(C)J.G.Harston":EQUB &00
  240   :
  250   .Service
  260   CMP #1:BNE NotService1
  270   LDA &28F:BNE Service1Done           :\ Keyboard isn't absent
  280   LDA &229:BPL Service1Done           :\ Somebody has already claimed KEYV
  290   LDX #7
  300   .Service1Lp
  310   LDA KeyIntercept,X:STA &3D0,X
  320   DEX:BPL Service1Lp                  :\ Copy intercept code to memory
  330   LDA &228:STA &3D8:LDA &229:STA &3D9 :\ Copy old KEYV to memory
  340   LDA #&D0:STA &228:LDA #3:STA &229   :\ Direct KEYV to intercept code
  350   .Service1Done
  360   LDX &F4:LDA #1                      :\ Restore registers
  370   .NotService1
  380   RTS                                 :\ And exit
  390   :
  400   .KeyIntercept
  410   BVS OldKeyJmp:BCS OldKeyJmp:LDA #0:RTS:.OldKeyJmp:EQUB &4C
  420   :
  430   ]:RelocTable=P%
  440 NEXT:ENDPROC
  450 :
  460 DEFFNsm_pass(pass%)
  470 IFpass%=0:M%=0
  480 IFpass%=1:M%=O%-mcode%
  490 P%=&8100-128*(pass%AND2)
  500 O%=mcode%+M%*(pass%AND2)DIV2
  510 IFpass%=1:IF O%+M%*2.125>L%:PRINT"Code overrun":END
  520 =VALMID$("4647",pass%+1,1)
  530 :
  540 DEFPROCsm_table
  550 base80%=mcode%+M%:base81%=mcode%:byte%=0:count%=0:off%=0:REPEAT
  560   byte80%=base80%?off%:byte81%=base81%?off%:IF off%>=M%:byte80%=&80:byte81%=&80
  570   IF ((byte81%-byte80%) AND &FE)<>0:PRINT "ERROR: Offset by more than one page at &";~&8000+off%
  580   IF (byte80% AND &C0)=&80:byte%=byte%DIV2+128*(byte81%-byte80%):count%=count%+1
  590   IF count%=8:?O%=byte%:O%=O%+1:byte%=0:count%=0
  600 off%=off%+1:UNTILoff%>=M% AND count%=0
  610 ENDPROC