10 REM > SETPATH/SRC
   20 REM Set SJCCP search path, and resave SJCCP to Acorn CPM disk system tracks
   30 :
   40 A%=0:X%=1:os%=(USR&FFF4 AND &FF00)DIV256:IF os%=6 AND PAGE>&8000:PRINT"Running Z80...":SYS "OS_GetEnv" TO A$:OSCLI"Z80 "+MID$(A$,INSTR(A$," ",1+INSTR(A$," "))):END
   50 unix%=os%=8:quit%=?&80<>0:?&80=0
   60 ON ERROR REPORT:PRINT" at line ";ERL:END
   70 DIM mcode% &800:start%=&100:ver$="0.01":name$="SETPATH/CO"
   80 :
   90 OSWORD=&FFF1:CLICOM=&FFB9:PRTEXT=&FFB3:OSNEWL=&FFE7
  100 PRHEX=&FFAA:PR2HEX=&FFAD:OSNEWL=&FFE7:DISKACC=&FFA4
  110 :
  120 REM CPM Entries:
  130 bdos=5:DRIVE=4
  140 bdos_string=9:bdos_open=15:bdos_close=16
  150 bdos_readseq=20:bdos_setdma=26
  160 :
  170 REM Memory locations:
  180 FCB1=&5C:FCB2=&6C:DMA=&80
  190 :
  200 FOR P=0 TO 1
  210   P%=start%:O%=mcode%
  220   [OPT P*3+4
  230   JP Start
  240   .msgSyntax
  250   DEF"Syntax: SETPATH <drive><user>":DEFB 13:DEFB 10
  260   DEF"$"
  270   .msgBadDrive
  280   DEF"Bad drive (floppy only)":DEFB 13:DEFB 10
  290   DEF"$"
  300   .msgBadNumber
  310   DEF"Bad number":DEFB 13:DEFB 10
  320   DEF"$"
  330   .msgNotSJ
  340   DEF"Not SJCCP":DEFB 13:DEFB 10
  350   DEF"$"
  360   :
  370   .errNotSJ
  380   LD DE,msgNotSJ:JR errAbort
  390   .errBadNumber
  400   LD DE,msgBadNumber:JR errAbort
  410   .errBadDrive
  420   LD DE,msgBadDrive:JR errAbort
  430   .errSyntax
  440   LD DE,msgSyntax
  450   .errAbort
  460   LD C,bdos_string:CALL bdos
  470   LD SP,(AbortSP):RET
  480   .AbortSP
  490   DEFW 0
  500   :
  510   .Start
  520   LD (AbortSP),SP:LD DE,DMA       :\ Point to command line
  530   LD A,(DMA):AND A:JR Z,errSyntax :\ No parameters
  540   INC DE:INC DE:LD A,(DE):AND &DF :\ Get drive character
  550   CP ASC"A":JR C,errSyntax        :\ <'A'
  560   CP ASC"O":JR NC,errSyntax       :\ >'N'
  570   AND 15:PUSH AF:INC DE           :\ Save drive
  580   CALL ReadDec:JR C,errBadNumber  :\ Get user number
  590   LD A,C:CP 16:JR NC,errBadNumber :\ User must be 0..15
  600   PUSH AF                         :\ Save user number
  610   LD A,(DRIVE):AND 15             :\ Get current drive
  620   CP 2:JR NC,errBadDrive          :\ Only drive 0-1 allowed
  630   LD (Load_1),A:LD (Save_1),A     :\ Set drive in control blocks
  640   LD HL,Load_1:Call DiskSectors   :\ Load first sector
  650   LD HL,Buffer                    :\ HL=>start of CCP
  660   LD DE,24:ADD HL,DE              :\ HL=>start of "SJ" message
  670   LD A,(HL):CP ASC"S":JR NZ,errNotSJ
  680   INC HL
  690   LD A,(HL):CP ASC"J":JR NZ,errNotSJ
  700   LD HL,Buffer                    :\ HL=>start of CCP
  710   .FindOffset
  720   LD A,(HL):INC HL:INC HL:INC HL  :\ Get byte, step to next
  730   CP &C3:JR Z,FindOffset          :\ Step though until not a JP
  740   LD E,A:ADD HL,DE                :\ HL=>SEARCH
  750   POP AF:RLD:POP AF:RLD:LD A,(HL) :\ Store USR+DRV
  760   LD DE,Buffer:AND A:SBC HL,DE    :\ HL=offset from start of buffer
  770   LD DE,(6):ADD HL,DE:LD DE,&F7FA :\ Point to SEARCH in current CCP in memory
  780   ADD HL,DE:LD (HL),A             :\ Store USR+DRV to take immediate effect
  790   .SaveBuffer
  800   LD HL,Save_1                    :\ Save first sector
  810   .DiskSectors
  820   JP DISKACC
  830   :
  840   .ReadDec
  850   XOR A
  860   .ReadDecLp
  870   LD C,A:LD A,(DE)
  880   CP ASC"!":CCF:RET NC            :\ NC=Ok
  890   INC DE:CP ASC":":CCF:RET C      :\ C=Bad Number
  900   SUB ASC"0":RET C                :\ C=Bad Number
  910   LD B,10
  920   .ReadDecAdd
  930   ADD A,C:RET C                   :\ C=Bad Number
  940   DJNZ ReadDecAdd:JR ReadDecLp
  950   :
  960   .Load_1                :\ First two sectors of CCP
  970   DEFB 0                 :\ Drive 0
  980   DEFW Buffer+0:DEFW 0   :\ Will load to &D400
  990   DEFB 3:DEFB &53        :\ READ
 1000   DEFB 0                 :\ Track
 1010   DEFB 8                 :\ Sector
 1020   DEFB &21               :\ One sectors
 1030   DEFB &FF
 1040   :
 1050   .Save_1                :\ First two sectors of CCP
 1060   DEFB 0                 :\ Drive 0
 1070   DEFW Buffer+0:DEFW 0   :\ Will load to &D400
 1080   DEFB 3:DEFB &4B        :\ WRITE
 1090   DEFB 0                 :\ Track
 1100   DEFB 8                 :\ Sector
 1110   DEFB &21               :\ One sectors
 1120   DEFB &FF
 1130   :
 1140   .Buffer                :\ CCP loaded to here to write to disk
 1150 ]NEXT
 1160 :
 1170 A$="*Save "+name$+" "+STR$~mcode%+" "+STR$~O%+" FFFF0000 "+STR$~(&FFF20000 OR start%)
 1180 PRINT " "A$:IF quit%:OSCLI A$:*Quit