10 REM > COPYROM/src 0.01
   20 REM 0.01 05-Feb-2015 J.G.Harston
   30 :
   40 PROCassem(0):CLEAR:PROCassem(2):PROCsm_table
   50 A$="*SAVE "+fname$+" "+STR$~(mcode%+M%)+" "+STR$~O%+" FFFF0000 FFFBBC00"
   60 PRINTA$;:OSCLIA$:PRINT
   70 END
   80 :
   90 DEFPROCassem(pass%)
  100 fname$="COPYROM"               :REM Saved filename
  110 title$="COPY"                  :REM ROM title
  120 vers$="0.01 (01 Jan 2015)"     :REM ROM version and date
  130 copy$="(C)J.G.Harston"         :REM Copyright message
  140 :
  150 ver%=VALvers$*10
  160 DIM mcode% &4800,L% -1
  170 OSASCI=&FFE3:OSNEWL=&FFE7:OSWRCH=&FFEE
  180 :
  190 FOR pass%=pass% TO pass%+1
  200   opt%=FNsm_pass(pass%)
  210   [OPT opt%
  220   .RomStart
  230   BRK:EQUW RelocTable
  240   JMP Service
  250   EQUB &82:EQUB Copyright-RomStart
  260   .RomTitle
  270   EQUB ver%:EQUS title$
  280   EQUB &00 :EQUS vers$
  290   .Copyright
  300   EQUB &00:EQUS copy$
  310   EQUB &00
  320   :
  330   .Service
  340   CMP #4:BEQ Serv4          :\ *command
  350   CMP #9:BNE NotServ9       :\ Not *Help
  360   LDA (&F2),Y
  370   CMP #13:BNE Serv9Skip     :\ Not *Help <cr>
  380   JSR OSNEWL:LDX #0
  390   .Serv9Lp
  400   LDA RomTitle+1,X          :\ Print ROM title
  410   BNE P%+4:LDA #ASC" "      :\ Convert &00 to <spc>
  420   CMP #ASC"(":BEQ Serv9Done :\ End at '('
  430   JSR OSWRCH:INX:BNE Serv9Lp
  440   .Serv9Done
  450   JSR OSNEWL
  460   .Serv9Skip
  470   LDA #9
  480   .NotServ9
  490   RTS
  500   :
  510   .Serv4
  520   TYA:PHA:DEY:LDX #&FF
  530   .Serv4Lp
  540   INX:INY:LDA (&F2),Y
  550   CMP #ASC".":BEQ Serv4Dot
  560   CMP #ASC"!":BCC Serv4End
  570   CMP RomTitle+1,X:BEQ Serv4Lp :\ Match with ROM title
  580   EOR #&20                     :\ Change case
  590   CMP RomTitle+1,X:BEQ Serv4Lp :\ Match with ROM title
  600   .Serv4Quit
  610   PLA:TAY                      :\ Restore Y
  620   .Serv4Exit
  630   LDA #4:RTS                   :\ Restore A and return unclaimed
  640   .Serv4End
  650   LDA RomTitle+1,X:BNE Serv4Quit
  660   DEY
  670   .Serv4Dot
  680   INY:LDA (&F2),Y              :\ Step past '.'
  690   CMP #ASC" ":BEQ Serv4Dot     :\ Skip any spaces
  700   :
  710   \ (&F2),Y => any parameters
  720   JSR CheckCopyCommand         :\ Pre-parse command line
  730   BNE NotDFSCopy               :\ Not DFS *COPY parameters
  740   PLA:TAY:LDA #4:RTS           :\ Return unclaimed to pass to filing system
  750   :
  760   .NotDFSCopy
  770   :
  780   \ Demo code, just print the command line
  790   PLA:TAY                      :\ Get command line pointer back
  800   .DemoLp
  810   LDA (&F2),Y:JSR OSASCI
  820   INY:CMP #13:BNE DemoLp
  830   :
  840   :
  850   LDA #0:RTS                   :\ Claim call and return
  860   :
  870   :
  880   \ Check command parameters to check for DFS *COPY syntax
  890   \ ------------------------------------------------------
  900   \ Returns A=0   DFS     "*COPY d d name" syntax
  910   \         A<>0  Generic "*COPY name name (options)" syntax
  920   \
  930   .CheckCopyCommand
  940   TYA:PHA                     :\ Save line pointer
  950   JSR chkdigit:BCS newcopy    :\ COPY x        x<>digit
  960   PHA
  970   JSR chkspc:BCS newcopy1     :\ COPY nxxxx    1st param not drive
  980   PLA
  990   CMP (&F2),Y:BEQ newcopy     :\ COPY x y      x=y
 1000   JSR chkdigit:BCS newcopy    :\ COPY x y      y<>digit
 1010   JSR chkspc:BCS newcopy      :\ COPY n nxxxx  2nd param not drive number
 1020   CMP #ASC" ":BCC newcopy     :\ COPY x y      only two parameters
 1030   LDX #2                      :\ option count
 1040   .loop
 1050   LDA (&F2),Y
 1060   CMP #ASC"~":BEQ newcopy     :\ COPY x y ...~...  copy option
 1070   CMP #ASC"*":BEQ oldcopy     :\ COPY x y ..*....  wildcard filename
 1080   CMP #ASC"#":BEQ oldcopy     :\ COPY x y ...#...  wildcard filename
 1090   CMP #ASC".":BEQ oldcopy     :\ COPY x y xxx.xxx  directory name
 1100   CMP #ASC" ":BNE chknext
 1110   DEX:BEQ newcopy             :\ COPY x y zzz zzz  multiple options
 1120   JSR skipspc
 1130   .chknext
 1140   INY:CMP #13:BNE loop
 1150   .oldcopy
 1160   PLA:TAY:LDA #0:RTS          :\ DFS COPY parameters
 1170   .newcopy1
 1180   PLA
 1190   .newcopy
 1200   PLA:TAY:LDA #1:RTS          :\ Generic COPY parameters
 1210   :
 1220   .chkspc
 1230   INY:LDA (&F2),Y
 1240   CMP #ASC" ":BNE chkdigit1   :\ SEC=no following space
 1250   .skipspc
 1260   INY:LDA (&F2),Y
 1270   CMP #ASC" ":BEQ skipspc
 1280   CLC:RTS                     :\ CLC=follow space, and skipped
 1290   :
 1300   .chkdigit
 1310   LDA (&F2),Y
 1320   CMP #ASC"0":BCC chkdigit1   :\ SEC=not a digit
 1330   CMP #ASC"9"+1:BCC chkdigit2 :\ CLC=is a digit
 1340   .chkdigit1
 1350   SEC
 1360   .chkdigit2
 1370   RTS
 1380   :
 1390   ]:RelocTable=P%
 1400 NEXT:ENDPROC
 1410 :
 1420 DEFFNsm_pass(pass%)
 1430 IFpass%=0:M%=0
 1440 IFpass%=1:M%=O%-mcode%
 1450 P%=&8100-128*(pass%AND2)
 1460 O%=mcode%+M%*(pass%AND2)DIV2
 1470 IFpass%=1:IF O%+M%*2.125>L%:PRINT"Code overrun":END
 1480 =VALMID$("4647",pass%+1,1)
 1490 :
 1500 DEFPROCsm_table
 1510 base80%=mcode%+M%:base81%=mcode%:byte%=0:count%=0:off%=0:REPEAT
 1520   byte80%=base80%?off%:byte81%=base81%?off%:IF off%>=M%:byte80%=&80:byte81%=&80
 1530   IF ((byte81%-byte80%) AND &FE)<>0 THEN PRINT "ERROR: Offset by more than one page at &";~&8000+off%
 1540   IF (byte80% AND &C0)=&80:byte%=byte%DIV2+128*(byte81%-byte80%):count%=count%+1
 1550   IF count%=8:?O%=byte%:O%=O%+1:byte%=0:count%=0
 1560 off%=off%+1:UNTILoff%>=M% AND count%=0
 1570 ENDPROC