10
20
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
130 bdos=5:DRIVE=4
140 bdos_string=9:bdos_open=15:bdos_close=16
150 bdos_readseq=20:bdos_setdma=26
160 :
170
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 DEFM "Syntax: SETPATH <drive><user>":DEFB 13:DEFB 10
260 DEFM "$"
270 .msgBadDrive
280 DEFM "Bad drive (floppy only)":DEFB 13:DEFB 10
290 DEFM "$"
300 .msgBadNumber
310 DEFM "Bad number":DEFB 13:DEFB 10
320 DEFM "$"
330 .msgNotSJ
340 DEFM "Not SJCCP":DEFB 13:DEFB 10
350 DEFM "$"
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