Subversion Repositories NedoOS

Rev

Rev 851 | Rev 1123 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download

  1. ;TODO %~dp0 (драйв и путь запуска)
  2. ;TODO %~t1 (дата-время 1-го параметра)
  3. ;TODO goto и метки :label
  4. ;TODO if ???==??? goto
  5. ;TODO for
  6. ;TODO PATH (где хранить? должна подгружаться при старте новой копии cmd)
  7.  
  8.         DEVICE ZXSPECTRUM128
  9.         include "../_sdk/sys_h.asm"
  10. MAXCMDSZ=COMMANDLINE_sz-1;127 ;не считая терминатора
  11. txtscrhgt=25
  12. txtscrwid=80
  13. CMDLINEY=24
  14.  
  15. _COLOR=0x0007;7
  16. _ERRORCOLOR=0x0009;0x42
  17.  
  18.         org PROGSTART
  19. cmd_begin
  20.         ld sp,0x4000 ;не должен опускаться ниже 0x3b00! иначе возможна порча OS        
  21.         call initstdio
  22.  
  23.         OS_GETSTDINOUT ;e=stdin, d=stdout, h=stderr
  24.         ld a,d
  25.         ld (stdouthandle_wasatstart),a
  26.         ld a,e
  27.         ld (stdinhandle_wasatstart),a
  28.  
  29.         OS_GETMAINPAGES
  30. ;dehl=номера страниц в 0000,4000,8000,c000
  31.         push hl
  32.         OS_DELPAGE
  33.         pop hl
  34.         push hl
  35.         ld e,h
  36.         OS_DELPAGE
  37.         pop hl
  38.         ld e,l
  39.         OS_DELPAGE
  40.  
  41.         ld hl,COMMANDLINE ;command line
  42.         push hl
  43.         ld de,params
  44.         call strcopy
  45.        
  46.         pop hl ;ld hl,COMMANDLINE ;command line
  47.         ld de,wordbuf
  48.         call getword
  49.         call skipspaces
  50.         ld (cmdlineword2),hl
  51.         ld a,(hl)
  52.         or a
  53.         jr z,cmd_interactive
  54. ;command line = "cmd <command to run>"
  55.         ld de,cmdbuf
  56.         call strcopy
  57.        
  58.         call makeprompt ;иначе запустится из неправильной директории
  59.        
  60.         call execcmd_maybepipes ;can show errors ;a!=0: no such internal command
  61.         ;or a
  62.         ;call nz,callcmd;strcpexec_tryrun ;запускает по фону
  63.         YIELD ;чтобы запущенная задача успела захватить фокус ;???
  64. ;если командная строка была со словом autoexec.bat в параметре, то это начальный запуск autoexec.bat, из него надо входить в интерактивный режим
  65.         ld hl,tautoexecbat
  66. cmdlineword2=$+1
  67.         ld de,0
  68.         call strcp ;z=yes
  69.         jr z,cmd_interactive
  70. cmd_exit
  71.         QUIT
  72.        
  73. tautoexecbat
  74.         db "autoexec.bat",0
  75.  
  76. cmd_interactive
  77.        
  78. cmdmainloop
  79.         call makeprompt
  80.         call editcmd
  81.         call prcrlf
  82.        
  83.         ld hl,cmdbuf
  84.         ld de,oldcmd
  85.         ld bc,MAXCMDSZ+1
  86.         ldir
  87.  
  88.         call execcmd_maybepipes
  89.         ;or a
  90.         ;call nz,callcmd;strcpexec_tryrun ;запускает по фону
  91.         xor a
  92.         ld (cmdbuf),a
  93.         ld (curcmdscroll),a
  94.         jp cmdmainloop
  95.  
  96. execcmd_maybepipes
  97. ;out:a!=0: no such internal command
  98. ;если command pars >file, то create file, перенаправить вывод в него, execcmd, close file, перенаправить вывод обратно
  99.         ld hl,cmdbuf
  100.         ld a,'|'
  101.         ld bc,MAXCMDSZ
  102.         cpir
  103.         jr z,execcmd_pipe
  104.  
  105.         ld hl,cmdbuf
  106.         ld a,'<'
  107.         ld bc,MAXCMDSZ
  108.         cpir
  109.         jr z,execcmd_changestdin ;jr nz,cmd_noexeccmdtofile
  110.  
  111.         ld hl,cmdbuf
  112.         ld a,'>'
  113.         ld bc,MAXCMDSZ
  114.         cpir
  115.         jp nz,callcmd ;exec or run ;execcmd_or_runprog ;jr nz,cmd_noexeccmdtofile
  116. ;change stdout
  117.         dec hl
  118.         ld (hl),0
  119.         inc hl
  120.          call skipspaces
  121.         ex de,hl ;de=filename
  122.         OS_CREATEHANDLE
  123.         ld a,b
  124.         ld (execcmdtofile_handle),a
  125.         call setstdouthandle
  126. ;changestdin_stdout_execcmd
  127.         ;call execcmd ;can show errors ;a!=0: no such internal command
  128.         ; or a
  129.         ; call nz,callcmd
  130.          call callcmd ;exec or run
  131.         ;push af
  132. ;команда выполнилась в блокирующем режиме и вышла
  133. execcmdtofile_handle=$+1
  134.         ld b,0
  135.         OS_CLOSEHANDLE ;закрыли выходной файл
  136. stdouthandle_wasatstart=$+1
  137.         ld a,0
  138.         call setstdouthandle
  139. ;stdinhandle_wasatstart=$+1
  140. ;        ld a,0
  141. ;        call setstdinhandle
  142.  
  143.         ;pop af
  144.         ret
  145.         ;jr cmd_noexeccmdtofileq
  146. ;cmd_noexeccmdtofile
  147. ;        jp execcmd ;a!=0: no such internal command
  148. ;cmd_noexeccmdtofileq
  149. ;        ret
  150.  
  151. execcmd_changestdin
  152.         dec hl
  153.         ld (hl),0
  154.         inc hl
  155.          call skipspaces
  156.         ex de,hl ;de=filename
  157.         OS_OPENHANDLE
  158.         ld a,b
  159.         ;ld (execcmdtofile_changestdin_handle),a
  160.         call setstdinhandle
  161.         call setstdinout
  162.         ;jr changestdin_stdout_execcmd
  163.         ;call execcmd ;can show errors ;a!=0: no such internal command
  164.         ; or a
  165.         ; call nz,callcmd
  166.          call callcmd ;exec or run
  167.         ;push af
  168. ;команда выполнилась в блокирующем режиме и вышла (или запустилась программа по фону)
  169.  
  170. ;execcmdtofile_changestdin_handle=$+1
  171. ;        ld b,0
  172. ;        OS_CLOSEHANDLE ;закрыли входной файл программы
  173. ;stdouthandle_wasatstart=$+1
  174. ;        ld a,0
  175. ;        call setstdouthandle
  176. stdinhandle_wasatstart=$+1
  177.         ld a,0
  178.         call setstdinhandle
  179.         call setstdinout
  180.  
  181.         ;pop af
  182.         ret
  183.         ;jr cmd_noexeccmdtofileq
  184.  
  185. execcmd_pipe
  186. ;cmd |app
  187.         dec hl
  188.         ld (hl),0
  189.         inc hl
  190.          call skipspaces
  191.         ex de,hl ;de=app filename
  192.  
  193.         OS_OPENHANDLE
  194.         or a
  195.         jr nz,execcmd_pipe_error
  196.  
  197.         push bc
  198.         ld de,tpipename
  199.         OS_CREATEHANDLE
  200.         ld a,b
  201.         ld (pipehandle),a
  202.         call setstdouthandle
  203.         pop bc
  204.        
  205.         call readapp ;делает CLOSE ;TODO через loadapp, чтобы дописывать .com и грузить из /bin
  206.        
  207.         if 1==1
  208.         push af
  209.         ld b,a
  210.         ;ld a,(stdinhandle)
  211.         ;ld d,a
  212. pipehandle=$+1
  213.         ld d,0
  214.         ld a,(stdouthandle)
  215.         ld e,a
  216.         ld h,0xff ;rnd
  217. ;b=id, e=stdin, d=stdout, h=stderr        
  218.         OS_SETSTDINOUT
  219.         endif
  220.        
  221.         pop af ;id
  222.  
  223.         ld e,a ;id
  224.         ;ld (waitpid_id),a
  225.         push de
  226.         OS_RUNAPP
  227.        
  228.         ;call execcmd ;can show errors ;a!=0: no such internal command
  229.         ; or a
  230.         ; call nz,callcmd
  231.          call callcmd ;exec or run
  232.         pop de
  233.         ;push af ;a=error
  234.         push de
  235.         ld a,(pipehandle)
  236.         ld b,a
  237.         OS_CLOSEHANDLE ;закрыли источник данных
  238.         pop de
  239.         WAITPID ;hl=result
  240.         call prword_hl_crlf
  241.  
  242.         ld a,(stdouthandle_wasatstart)
  243.         call setstdouthandle
  244. ;закрыть входной файл правой программы
  245.         ;ld a,(pipehandle)
  246.         ;ld b,a
  247.         ;OS_CLOSEHANDLE
  248.  
  249.         ;pop af ;a=error
  250. execcmd_pipe_error
  251.         ret
  252.  
  253. tpipename
  254.         db "z:",0
  255.  
  256. ;;;;;;;;;;;;;;;;;;
  257.        
  258. editcmd_up
  259.         xor a
  260.         ld (curcmdscroll),a
  261.         ld de,cmdbuf
  262.         ld hl,oldcmd
  263.         ld bc,MAXCMDSZ+1
  264.         ldir
  265.         ;jp editcmd
  266.  
  267. editcmd
  268.         ld hl,cmdbuf
  269.         call strlen
  270.         ld a,l
  271.         ld (curcmdx),a
  272. editcmd0
  273.         call fixscroll_prcmd
  274.         call cmdcalccurxy
  275.         SETX_;SETXY_
  276.         ;ld e,CURSORCOLOR;0x38
  277.         ;OS_PRATTR ;нарисовать курсор
  278.         call yieldgetkeyloop ;YIELDGETKEYLOOP
  279.          ;ld a,c ;keynolang
  280.         ;push af
  281.         ;call cmdcalccurxy
  282.         ;SETXY_
  283.         ;ld e,COLOR;7
  284.         ;OS_PRATTR ;стереть курсор
  285.         ;pop af
  286.         cp key_enter
  287.         ret z
  288.         cp key_up
  289.         jr z,editcmd_up
  290.          ld hl,editcmd0
  291.          push hl
  292.         ;ld hl,cmdbuf
  293.         cp key_backspace
  294.         jr z,editcmd_backspace
  295.         cp key_left
  296.         jr z,editcmd_left
  297.         cp key_right
  298.         jr z,editcmd_right
  299.         cp key_home
  300.         jr z,editcmd_home
  301.         cp key_end
  302.         jr z,editcmd_end
  303.         cp key_del
  304.         jr z,editcmd_del
  305.         cp 0x20
  306.         ret c ;jr c,editcmdok ;прочие системные кнопки не нужны
  307. ;type in
  308. editcmdtypein
  309.         ld e,a
  310.         ld hl,cmdbuf
  311.         call strlen ;hl=length
  312.         ld bc,MAXCMDSZ
  313.         or a
  314.         sbc hl,bc
  315.         ret nc ;jr nc,editcmdok ;некуда вводить
  316.         call cmdcalctextaddr ;hl=addr, a=curcmdx
  317.         inc a
  318.         ld (curcmdx),a
  319.         jp strinsch ;e=ch
  320.        
  321. editcmd_backspace
  322.         call cmdcalctextaddr ;hl=addr, a=curcmdx
  323.         or a
  324.         ret z ;jr z,editcmdok ;нечего удалять
  325.         dec a
  326.         ld (curcmdx),a
  327.         jp strdelch ;удаляет предыдущий символ
  328.      
  329. editcmd_del
  330.         call cmdcalctextaddr ;hl=addr, a=curcmdx
  331.         inc hl
  332.         jp strdelch ;удаляет предыдущий символ
  333.      
  334. editcmd_left
  335.         ld a,(curcmdx)
  336.         or a
  337.         ret z ;jr z,editcmdok ;некуда влево
  338.         dec a
  339. editcmd_leftq
  340.         ld (curcmdx),a
  341.         ret
  342. editcmd_home
  343.         xor a
  344.         jr editcmd_leftq
  345. editcmd_end
  346.         ld hl,cmdbuf
  347.         call strlen ;hl=length
  348.         ld a,l
  349.         jr editcmd_leftq
  350.  
  351. editcmd_right
  352.         call cmdcalctextaddr ;hl=addr, a=curcmdx
  353.         inc (hl)
  354.         dec (hl)
  355.         ret z ;jr z,editcmdok ;некуда право, стоим на терминаторе
  356.         inc a
  357.         ld (curcmdx),a
  358.         ret
  359.  
  360. getword
  361. ;hl=string
  362. ;de=wordbuf
  363. ;out: hl=terminator/space addr
  364. getword0
  365.         ld a,(hl)
  366.         or a
  367.         jr z,getwordq
  368.         sub ' '
  369.         jr z,getwordq
  370.         ldi
  371.         jp getword0
  372. getwordq
  373.         ;xor a
  374.         ld (de),a
  375.         ret
  376.  
  377. execcmd
  378. ;a=0: command executed
  379. ;a!=0: no such internal command
  380.         ld hl,cmdbuf
  381.         ld a,(hl)
  382.         or a
  383.         ret z
  384.                 ;display $
  385.                 ;display wordbuf
  386.         ld de,wordbuf
  387.         call getword ;hl=terminator/space addr
  388.         call skipspaces
  389.         ld (execcmd_pars),hl
  390.                 inc hl
  391.                 ld a,(wordbuf+1)
  392.                 cp ':'
  393.                 jp nz,execcmd0
  394.                 ld a,(wordbuf+2)
  395.                 or a
  396.                 jp z,cmd_t0
  397. execcmd0
  398.         ld hl,commandslist ;list of internal commands
  399. strcpexec0
  400.         ld c,(hl)
  401.         inc hl
  402.         ld b,(hl)
  403.         inc hl
  404.         ld a,b
  405.         cp -1
  406.         ret z ;jr z,strcpexec_tryrun ;a!=0: no such internal command
  407.         ld de,wordbuf
  408.         push hl
  409.         call strcp
  410.         pop hl
  411.         jr nz,strcpexec_fail
  412.         ld h,b
  413.         ld l,c
  414.         call jphl ;execute command
  415.         xor a
  416.         ret ;a=0: command executed
  417. jphl
  418.         jp (hl) ;run internal command
  419. strcpexec_fail
  420.         ld b,-1 ;чтобы точно найти терминатор
  421.         xor a
  422.         cpir ;найдём обязательно
  423.         jr strcpexec0
  424.  
  425. cmd_start
  426. ;выполнить командную строку по фону (нужно из .bat)
  427.         ld hl,cmdbuf
  428.         ld a,(hl)
  429.         or a
  430.         ret z
  431.         ld de,wordbuf
  432.         call getword ;hl=terminator/space addr
  433.         call skipspaces
  434.         ld de,cmdbuf
  435.         ld bc,MAXCMDSZ+1
  436.         ldir
  437.         call strcpexec_tryrun ;выполнить файл с именем cmdbuf или SYSDIR/cmdbuf и параметрами там, e=id, nz=error, cy=end of .bat
  438.         ret z
  439. execcmd_error
  440.         ld hl,tunknowncommand
  441.         jp cmderror
  442.        
  443. strcpexec_tryrun
  444. ;выполнить файл с именем cmdbuf или SYSDIR/cmdbuf и параметрами там, e=id, nz=error, cy=end of .bat
  445.         call loadapp ;загрузить файл с именем cmdbuf, e=id, nz=error, cy=end of .bat
  446.         ret c ;cy=end of .bat        
  447.         jr nz,execcmd_tryrunerror
  448. execcmd_tryrunok
  449.         ret c ;cy=end of .bat
  450.         push de
  451.         OS_RUNAPP ;e=id
  452.         pop de
  453.          xor a ;z
  454.         ret
  455.  
  456. execcmd_tryrunerror
  457. ;выполнить файл с именем SYSDIR/cmdbuf и параметрами там
  458.         call loadapp_keeppath
  459.         OS_SETSYSDRV
  460.         ld de,sysdir
  461.         push de
  462.         OS_GETPATH
  463.         call loadapp_setoldpath ;TODO из prompt
  464.          ;OS_SETSYSDRV
  465.          ;ld de,wordbuf2
  466.          ;OS_GETPATH
  467.         ;ld de,cmdprompt
  468.         ;OS_CHDIR
  469.         ;call makeprompt
  470.         ;ld de,cmdprompt
  471.         ;OS_CHDIR
  472.         pop hl
  473.         push hl
  474. ;если в конце нет слеша, то добавим:
  475.         ;ld bc,0 ;чтобы точно найти терминатор
  476.         xor a
  477.         ld b,a
  478.         ld c,a;0
  479.         cpir ;найдём обязательно, если длина=0, то bc=-1 и т.д.
  480.         dec hl ;на терминаторе
  481.         dec hl ;перед терминатором
  482.         ld a,'/'
  483.         cp (hl)
  484.         jr z,$+2+5
  485.          inc hl
  486.          ld (hl),a
  487.          inc hl
  488.          ld (hl),0
  489.         pop hl ;sysdir
  490.         call strlen
  491.         ld b,h
  492.         ld c,l ;bc=SYSDIR_size
  493.          push bc ;SYSDIR_size
  494.         ld hl,MAXCMDSZ+1
  495.         or a
  496.         sbc hl,bc
  497.         push hl ;MAXCMDSZ+1-SYSDIR_size
  498. ;bc=SYSDIR_size
  499.         ld hl,cmdbuf+MAXCMDSZ;+1
  500.         or a
  501.         sbc hl,bc
  502.         ld de,cmdbuf+MAXCMDSZ;+1
  503.         pop bc ;MAXCMDSZ+1-SYSDIR_size
  504.         lddr
  505.         ld hl,sysdir
  506.         ld de,cmdbuf
  507.          pop bc ;SYSDIR_size
  508.         ldir ;нельзя strcopy, т.к. не нужен терминатор
  509.          ;ld hl,sysdir
  510.          ;ld de,oldpath
  511.          ;ld bc,MAXPATH_sz;MAXCMDSZ+1
  512.          ;ldir ;TODO рекурсивно (для .bat)
  513.          ;jr $
  514.         call loadapp ;загрузить файл с именем cmdbuf, e=id, nz=error, cy=end of .bat
  515.         jr z,execcmd_tryrunok
  516.         ret ;nz=error
  517.        
  518. openparams
  519. ;open %0 (progname), %1...
  520.         ld hl,cmdbuf
  521.         call strlen
  522.         ld b,h
  523.         ld c,l ;bc=len (without terminator)
  524.         ld hl,cmdbuf
  525.         add hl,bc ;at terminator
  526.         ld de,cmdbuf+MAXCMDSZ ;at last byte of buffer
  527.         inc bc ;bc=len (with terminator)
  528.         lddr
  529.         ex de,hl
  530.         inc hl
  531.         ld de,cmdbuf
  532. chgparams0
  533.         ld a,(hl)
  534.         ld (de),a
  535.         or a
  536.         jr z,chgparams0q
  537.         inc hl
  538.         cp '%'
  539.         jr nz,chgparams0skip
  540.         ld a,(hl)
  541.         ld (de),a
  542.         or a
  543.         jr z,chgparams0q
  544.         inc hl
  545.         sub '0' ;a=param
  546.         cp 10
  547.         jr nc,chgparams0skip ;%%
  548.         push hl
  549.         ld hl,params
  550.         inc a
  551.         ld b,a
  552. chgparams1
  553.         call skipword ;doesn't move at terminator
  554.         call skipspaces ;doesn't move at terminator
  555.         djnz chgparams1
  556. ;hl=param text (end=space or terminator)        
  557. chgparams2
  558.         ld a,(hl)
  559.         or a
  560.         jr z,chgparams2q
  561.         cp ' '
  562.         jr z,chgparams2q
  563.         ld (de),a
  564.         inc hl
  565.         inc de
  566.         djnz chgparams2
  567. chgparams2q
  568.         pop hl
  569.         dec de
  570. chgparams0skip
  571.         inc de
  572.         jr chgparams0
  573. chgparams0q
  574.         ret
  575.  
  576. ;execcmd_or_runprog
  577. ;        call execcmd
  578. ;        or a
  579. ;        ret z
  580. ;        jp callcmd;strcpexec_tryrun ;запускает по фону
  581.  
  582. callcmd
  583. ;call command (cmdbuf) with waiting
  584.         call execcmd ;a!=0: no such internal command
  585.         or a
  586.         ret z ;command executed
  587.         ;call loadapp ;загрузить файл с именем cmdbuf, e=id
  588.         call strcpexec_tryrun ;загрузить файл с именем cmdbuf или SYSDIR/cmdbuf, e=id, nz=error, CY=end of .bat
  589.         ret c
  590.         jp nz,execcmd_error
  591.         ;push de
  592.         ;OS_RUNAPP
  593.         ;pop de
  594.         WAITPID ;не должно быть, если команда была .bat!
  595. ;hl=result
  596.         jp prword_hl_crlf
  597.  
  598. loadapp_keeppath
  599.         ld hl,cmdprompt
  600.         ld de,oldpath
  601.         ld bc,MAXPATH_sz;MAXCMDSZ+1
  602.         ldir ;TODO рекурсивно (для .bat)
  603.         ret
  604.  
  605. loadapp_setoldpath
  606.         push de
  607.         ld de,oldpath ;TODO рекурсивно (для .bat)
  608.         OS_CHDIR
  609.         pop de
  610.         xor a
  611.         ret ;Z
  612.        
  613. loadapp
  614. ;out: nz=error, cy=end of .bat, or else e=id
  615.         ld hl,cmdbuf
  616.         ld de,wordbuf
  617.         call getword
  618. ;учесть путь в имени (TODO использовать OS_OPENHANDLE)
  619.         ld hl,wordbuf
  620.         push hl
  621.         call findlastslash. ;de=after last slash or beginning of path
  622.         pop hl
  623.  
  624.         ;push hl
  625. ;ищем точку, проверяем, что после неё стоит .com или .bat
  626. loadapp_finddot0
  627.         ld a,(hl)
  628.         or a
  629.         jr z,loadapp_nodot
  630.         cp '.'
  631.         inc hl
  632.         jr nz,loadapp_finddot0
  633. ;проверяем, что после неё стоит .com или .bat
  634.         ld a,(hl)
  635.         or 0x20
  636.         cp 'b'
  637. ; TODO где проверка на остальные буквы?
  638.         jp z,strcpexec_tryrun_bat
  639. ;считаем, что написано .com (в принципе расширение безразлично - просто запускаем)
  640.         jr loadapp_finddotok
  641. loadapp_nodot
  642. ;a=0
  643.         ld (hl),'.'
  644.         inc hl
  645.         ld (hl),'c'
  646.         inc hl
  647.         ld (hl),'o'
  648.         inc hl
  649.         ld (hl),'m'
  650.         inc hl
  651.         ld (hl),a ;0        
  652. loadapp_finddotok
  653.         ld de,wordbuf ;pop de
  654.         OS_OPENHANDLE
  655.         or a
  656.          push af
  657.         ld a,b
  658.         ld (curhandle),a
  659.          call loadapp_setoldpath
  660.          pop af
  661.         ret nz ;jr nz,execcmd_error ;NC!
  662.         OS_NEWAPP ;на момент создания должна быть включена текущая директория!!!
  663.         or a
  664.         ret nz ;error ;NC!
  665. ;dehl=номера страниц в 0000,4000,8000,c000 нового приложения, b=id, a=error
  666.         push bc ;b=id
  667.         ld a,d
  668.         SETPG32KHIGH
  669.         push de
  670.         push hl
  671.         ld hl,cmdbuf
  672.         ld de,0xc000+COMMANDLINE
  673.         ld bc,COMMANDLINE_sz
  674.         ldir ;command line
  675.         pop hl
  676.         pop de
  677.         call readfile_pages_dehl
  678.  
  679.         ld a,(curhandle)
  680.         ld b,a
  681.         OS_CLOSEHANDLE
  682.         pop de
  683.         ld e,d ;e=id
  684.         xor a
  685.         ret ;Z
  686.      
  687. readapp
  688.         ld a,b
  689.         ld (curhandle),a
  690.        
  691.         OS_NEWAPP ;для первой создаваемой задачи будут созданы первые два пайпа и подключены
  692. ;dehl=номера страниц в 0000,4000,8000,c000 нового приложения, b=id, a=error
  693.         push bc ;b=id
  694.  
  695.         ld a,d
  696.         SETPG32KHIGH
  697.         push de
  698.         push hl
  699.         ld hl,COMMANDLINE ;command line
  700.         call skipword
  701.         call skipspaces ;пропустили первое слово (там было term.com, а дальше, например, cmd.com autoexec.bat)
  702.         ld de,0xc080
  703.         ld bc,128  
  704.         ldir ;command line
  705.         pop hl
  706.         pop de
  707.  
  708.         call readfile_pages_dehl
  709.  
  710.         ld a,(curhandle)
  711.         ld b,a
  712.         OS_CLOSEHANDLE
  713.  
  714.         pop af ;id
  715.         ret
  716.  
  717. skipword
  718. ;hl=string
  719. ;out: hl=terminator/space addr
  720. skipword0
  721.         ld a,(hl)
  722.         or a
  723.         ret z ;jr z,skipwordq
  724.         sub ' '
  725.         ret z ;jr z,skipwordq
  726.         inc hl ;ldi
  727.         jr skipword0
  728.  
  729. readfile_pages_dehl
  730.         ld a,d
  731.         SETPG32KHIGH
  732.         ld a,0xc100/256
  733.         call cmd_loadpage
  734.         ret nz
  735.         ld a,e
  736.         call cmd_loadfullpage
  737.         ret nz
  738.         ld a,h
  739.         call cmd_loadfullpage
  740.         ret nz
  741.         ld a,l
  742. cmd_loadfullpage
  743.         SETPG32KHIGH
  744.         ld a,0xc000/256
  745. cmd_loadpage
  746. ;out: a=error
  747. ;keeps hl,de
  748.         push de
  749.         push hl
  750.         ld d,a
  751.         xor a
  752.         ld l,a
  753.         ld e,a
  754.         sub d
  755.         ld h,a ;de=buffer, hl=size
  756. curhandle=$+1
  757.         ld b,0
  758.         OS_READHANDLE
  759.         pop hl
  760.         pop de
  761.         or a
  762.         ret
  763.      
  764. strcpexec_tryrun_bat
  765.         ;display "strcpexec_tryrun_bat",strcpexec_tryrun_bat
  766. ;out: nz=error, cy=end of .bat
  767. ;open .bat
  768. ;filename in wordbuf
  769.         ld de,wordbuf ;pop de
  770.         OS_OPENHANDLE
  771.         or a
  772.         ld a,b
  773.         ld (curbathandle),a    
  774.         ret nz ;jp nz,execcmd_error ;NC!
  775.        
  776.          ld a,0x3c ;"inc a"
  777.          ld (readbyte_readbuf_last),a
  778.         ld iy,file_buf_end
  779. strcpexec_tryrun_bat0
  780. ;load line to cmdbuf
  781.         ld hl,cmdbuf
  782.         LD (hl),0
  783.         call readstr ;nz=EOF
  784.         push af ;jr nz,strcpexec_tryrun_batq ;чтобы последнюю строку всё-таки выполнить
  785.  
  786.         push iy
  787.         ld hl,cmdbuf
  788.         call prtext
  789.         call prcrlf
  790.         pop iy
  791.        
  792. ;call command in cmdbuf
  793.         push iy
  794.         call openparams
  795.         call execcmd_maybepipes ;callcmd
  796.         pop iy
  797.        
  798.         pop af
  799.         jr z,strcpexec_tryrun_bat0 ;nz=EOF
  800. strcpexec_tryrun_batq
  801. ;close .bat
  802.         ld a,(curbathandle)
  803.         ld b,a
  804.         OS_CLOSEHANDLE
  805.         xor a
  806.          scf ;чтобы на выходе не делать RUNAPP
  807.         ret ;Z
  808.  
  809.         macro READBYTE_A
  810. ;out: z=EOF
  811.         inc ly
  812.         call m,readbyte_readbuf
  813.         ld a,(iy)
  814.         endm
  815.  
  816. readstr
  817. ;out: nz=EOF
  818. ;skips empty lines!
  819.         READBYTE_A ;z=EOF
  820.         jr z,readstrEOF
  821.         cp 0x0d
  822.         jr z,readstr ;empty string - retry
  823.         cp 0x0a
  824.         jr z,readstr ;empty string - retry
  825.         ld b,MAXCMDSZ
  826.         jr readstr0go
  827. readstr0
  828.         READBYTE_A ;z=EOF
  829.         jr z,readstrEOF ;возвращает NZ
  830.         ;jr z,readstrq ;возвращает Z
  831.         cp 0x0d
  832.         jr z,readstrq
  833.         cp 0x0a
  834.         jr z,readstrq
  835. readstr0go
  836.         ld (hl),a
  837.         inc hl
  838.         djnz readstr0
  839. readstrq
  840.         xor a ;Z
  841.         ld (hl),a
  842.         inc hl
  843.         ret ;Z
  844. readstrEOF
  845.         xor a
  846.         ld (hl),a
  847.         inc hl
  848.         dec a
  849.         ret ;NZ
  850.  
  851. readbyte_readbuf
  852. ;out: z=EOF
  853.         push bc
  854.         push de
  855.         push hl
  856.         push ix
  857.          ;jr $
  858.         xor a
  859. readbyte_readbuf_last=$ ;TODO keep if recursive!
  860.         inc a ;/nop(z)=last, inc a(nz)=not last
  861.         jr z,readbyte_readbufq
  862.  
  863.         if 1==1
  864. ;B = file handle, DE = Buffer address, HL = Number of bytes to read
  865. curbathandle=$+1
  866.         ld b,0
  867.         ld de,file_buf
  868.         push de
  869.         ld hl,128
  870.         OS_READHANDLE
  871.         pop iy
  872. ;HL = Number of bytes actually read, A=error
  873.         ;sub 1
  874.         ;sbc a,a ;error=0 => a=255, else a=0 (Z)
  875.         ;jr z,readbyte_readbufq ;error (=>EOF)
  876.          ;jr $
  877.         ld a,l
  878.         or a
  879.         jr z,readbyte_readbufq ;0 bytes (=>EOF)
  880.         jp m,readbyte_readbufq ;128 bytes (NZ no EOF) (not last block)
  881.        
  882.         else ;CP/M-like
  883.        
  884.         ld de,file_buf
  885.         push de
  886.         OS_SETDTA ;set disk transfer address = de
  887.         ld de,fcb_bat
  888.         OS_FREAD
  889.         pop iy
  890.         xor 128 ;a = bytes read
  891.         jr z,readbyte_readbufq
  892.         jp m,readbyte_readbufq ;full block = not last block
  893.        
  894.         endif
  895.        
  896. ;last block: shift data to the end of buf, mark last
  897.         ld c,a ;1..128
  898.         ld b,0 ;nz!
  899.         ld a,b
  900.         ld (readbyte_readbuf_last),a ;last block
  901.         ld hl,file_buf
  902.         add hl,bc
  903.         dec hl ;end of data
  904.         ld de,file_buf+127
  905.         lddr
  906.         inc de
  907.         push de
  908.         pop iy
  909.         ;nz!
  910. readbyte_readbufq
  911. ;iy=addr
  912. ;z=EOF
  913.         pop ix
  914.         pop hl
  915.         pop de
  916.         pop bc
  917.         ret
  918.  
  919. cmd_dir
  920.         ld de,(execcmd_pars)
  921.         ;ld de,emptypath
  922.         OS_OPENDIR
  923.         or a
  924.         ld bc,0 ;nfiles
  925.         jp nz,loaddir2_error
  926. cmd_dir2_0
  927.        push bc
  928.         ld de,filinfo
  929.         OS_READDIR
  930.        pop bc
  931.         or a
  932.         jr nz,loaddir2q
  933.         ld a,(filinfo+FILINFO_FNAME)
  934.         or a
  935.         jr z,loaddir2q
  936.        push bc
  937.         ld ix,(filinfo+FILINFO_FDATE)
  938.         ld hl,(filinfo+FILINFO_FTIME)
  939.         call prdate_time
  940.  
  941.         ld a,' '
  942.         PRCHAR_
  943.  
  944.         ld hl,(filinfo+FILINFO_FSIZE+2)
  945.         exx
  946.         ld hl,(filinfo+FILINFO_FSIZE)
  947.         call prdword
  948.         ld a,' '
  949.         PRCHAR_
  950.  
  951.         ld hl,filinfo+FILINFO_LNAME
  952.         ld a,(hl)
  953.         or a
  954.         jr nz,$+5
  955.         ld hl,filinfo+FILINFO_FNAME
  956.         ;ld c,0 ;c=x
  957.         call prtext
  958. ;c=x
  959.        
  960.         call prcrlf
  961.        pop bc ;nfiles
  962.         inc bc ;nfiles
  963.         or a
  964.         jr cmd_dir2_0
  965. loaddir2_error
  966. loaddir2q
  967. ;bc=nfiles
  968.         ld h,b
  969.         ld l,c
  970.         call prword
  971.         ld hl,t_files_crlf
  972.         jp prtext
  973.  
  974. prdate_time
  975. ;ix=date, hl=time
  976.         ld de,datetimebuf
  977.        push de
  978.        push hl ;time
  979.         ;push ix ;date
  980.         ld a,hx
  981.         srl a
  982.         sub 20
  983.         jr nc,$+4
  984.         add a,100 ;XX century
  985.         call prNNcmd ;year
  986.         ;ld a,'-'
  987.         ;PRCHAR_
  988.          inc de
  989.         ;pop hl
  990.         ld a,lx
  991.         push af
  992.         add ix,ix
  993.         add ix,ix
  994.         add ix,ix
  995.         ld a,hx
  996.         and 0x0f
  997.         call prNNcmd ;month
  998.         ;ld a,'-'
  999.         ;PRCHAR_
  1000.          inc de
  1001.         pop af
  1002.         and 0x1f
  1003.         call prNNcmd ;day
  1004.  
  1005.         ;ld a,' '
  1006.         ;PRCHAR_
  1007.          inc de
  1008.        pop hl ;time
  1009.         push hl
  1010.         ld a,h
  1011.         rra
  1012.         rra
  1013.         rra
  1014.         and 0x1f
  1015.         call prNNcmd ;hour
  1016.         ;ld a,':'
  1017.         ;PRCHAR_
  1018.          inc de
  1019.         pop hl
  1020.         ld a,l
  1021.         push af
  1022.         add hl,hl
  1023.         add hl,hl
  1024.         add hl,hl
  1025.         ld a,h
  1026.         and 0x3f
  1027.         call prNNcmd ;minute
  1028.         ;ld a,':'
  1029.         ;PRCHAR_
  1030.          inc de
  1031.         pop af
  1032.         add a,a
  1033.         and 0x3f
  1034.         call prNNcmd ;second
  1035.        pop hl
  1036.         ld de,8+1+8
  1037.         jp cmdprNchars
  1038.  
  1039. prNNcmd
  1040. ;a=NN
  1041. ;de=buf
  1042.         ld bc,10+(256*('0'-1))
  1043.         sub c
  1044.         inc b
  1045.         jr nc,$-2
  1046.          ex de,hl
  1047.          ld (hl),b
  1048.          ex de,hl
  1049.          inc de
  1050.         add a,'0'+10
  1051.          ld (de),a
  1052.          inc de
  1053.         ret
  1054.  
  1055. datetimebuf
  1056.         db "00-00-00 00:00:00"
  1057.        
  1058. skipspaces
  1059. ;hl=string
  1060. ;out: hl=after last space
  1061.         ld a,(hl)
  1062.         cp ' '
  1063.         ret nz
  1064.         inc hl
  1065.         jr skipspaces
  1066.  
  1067. strcopy
  1068. ;hl->de
  1069. strcopy0
  1070.         ld a,(hl)
  1071.         ldi
  1072.         or a
  1073.         jr nz,strcopy0
  1074.         ret
  1075.  
  1076. cmd_cd
  1077. execcmd_pars=$+1
  1078.         ld hl,0
  1079.         ld a,(hl)
  1080.         or a
  1081.         jr z,cmd_error_nopars
  1082.         ex de,hl ;de=path
  1083.         OS_CHDIR
  1084.         or a
  1085.         ret z
  1086.         ld hl,twrongpath
  1087.         jp cmderror
  1088.        
  1089. cmd_error_nopars
  1090.         ld hl,tnopars
  1091.         jp cmderror
  1092. cmd_error_notenoughpars
  1093.         ld hl,tnotenoughpars
  1094.         jp cmderror
  1095.  
  1096. cmd_md
  1097.         ld hl,(execcmd_pars)
  1098.         ld a,(hl)
  1099.         or a
  1100.         jr z,cmd_error_nopars
  1101.         ex de,hl ;de=dirname
  1102.         OS_MKDIR
  1103.         or a
  1104.         ret z
  1105. cmd_error_cantmakedir
  1106.         ld hl,tcantmakedir
  1107.         jp cmderror
  1108.        
  1109. cmd_del
  1110.         ld hl,(execcmd_pars)
  1111.         ld a,(hl)
  1112.         or a
  1113.         jr z,cmd_error_nopars
  1114.         ex de,hl
  1115.         OS_DELETE
  1116.         or a
  1117.         ret z
  1118. cmd_error_wrongfile
  1119.         ld hl,twrongfile
  1120.         jp cmderror
  1121.        
  1122. cmd_ren
  1123.         ld hl,(execcmd_pars)
  1124.         ld a,(hl)
  1125.         or a
  1126.         jr z,cmd_error_nopars
  1127.         ld de,wordbuf
  1128.         call getword ;hl=terminator/space addr
  1129.         call skipspaces
  1130.         ld a,(hl)
  1131.         or a
  1132.         jr z,cmd_error_notenoughpars
  1133.         ld de,wordbuf2
  1134.         call getword ;hl=terminator/space addr
  1135.         ld de,wordbuf
  1136.         ld hl,wordbuf2
  1137.         OS_RENAME
  1138.         or a
  1139.         ret z
  1140.         ld hl,tcantrename
  1141.         jp cmderror
  1142.        
  1143. cmd_copy
  1144.         ld hl,(execcmd_pars)
  1145.         ld a,(hl)
  1146.         or a
  1147.         jr z,cmd_error_nopars
  1148.         ld de,filenamebuf;wordbuf
  1149.         call getword ;hl=terminator/space addr
  1150.         call skipspaces
  1151.         ld a,(hl)
  1152.         or a
  1153.         jr z,cmd_error_notenoughpars
  1154.         ld de,filenamebuf2;wordbuf2
  1155.         call getword ;hl=terminator/space addr
  1156.  
  1157.         ld de,filenamebuf;wordbuf ;de=drive/path/file
  1158.         OS_OPENHANDLE
  1159.         or a
  1160.         jp nz,cmd_error_wrongfile
  1161.         ld a,b
  1162.         ld (close_file1_handle),a
  1163.         ld hl,close_file1
  1164.         push hl
  1165.        
  1166.         ld de,filenamebuf2;wordbuf2 ;de=drive/path/file
  1167.         OS_CREATEHANDLE
  1168.         or a
  1169.         jp nz,cmd_error_cant_copy
  1170.         ld a,b
  1171.         ld (cmd_copy_close_file2_handle),a
  1172.         ld hl,cmd_copy_close_file2
  1173.         push hl
  1174. cmd_copy0
  1175.         ld hl,copybuf_sz
  1176.         ld de,copybuf
  1177.         ld a,(close_file1_handle)
  1178.         ld b,a
  1179. ;B = file handle, DE = Buffer address, HL = Number of bytes to read
  1180.         push de
  1181.         OS_READHANDLE
  1182. ;HL = Number of bytes actually read, A=error
  1183.         pop de
  1184.         ld a,h
  1185.         or l
  1186.         ret z ;0 bytes remain
  1187.         ld a,(cmd_copy_close_file2_handle)
  1188.         ld b,a
  1189. ;B = file handle, DE = Buffer address, HL = Number of bytes to write
  1190.         OS_WRITEHANDLE
  1191.         jr cmd_copy0
  1192.        
  1193. close_file1
  1194. close_file1_handle=$+1
  1195.         ld b,0
  1196.         OS_CLOSEHANDLE
  1197.         ret
  1198.        
  1199. cmd_copy_close_file2
  1200. cmd_copy_close_file2_handle=$+1
  1201.         ld b,0
  1202.         OS_CLOSEHANDLE
  1203.         ld de,filenamebuf;wordbuf;filenametext
  1204.         OS_GETFILETIME ;ix=date, hl=time
  1205.         ld de,filenamebuf2;wordbuf2
  1206.         OS_SETFILETIME
  1207.         ret      
  1208.        
  1209. cmd_error_cant_copy
  1210.         ld hl,tcantcopy
  1211.         jp cmderror
  1212.  
  1213. cmd_rem
  1214.         ret
  1215.        
  1216. cmd_mem
  1217.         ld hl,tfree
  1218.         call prtext
  1219.         ld b,0
  1220. cmd_mem0
  1221.         push bc
  1222.         OS_NEWPAGE
  1223.         pop bc
  1224.         or a
  1225.         jr nz,cmd_mem_del
  1226.         inc b
  1227.         push de
  1228.         jr cmd_mem0
  1229. cmd_mem_del
  1230.         ld c,b
  1231.         inc b
  1232.         dec b
  1233.         jr z,cmd_mem_q
  1234. cmd_mem_del0
  1235.         pop de
  1236.         push bc
  1237.         OS_DELPAGE
  1238.         pop bc
  1239.         djnz cmd_mem_del0
  1240. cmd_mem_q
  1241. ;c=free pages
  1242.         ld l,c
  1243.         ld h,0
  1244. prword_hl_crlf
  1245.         call prword
  1246.         jp prcrlf
  1247.  
  1248. cmd_drop
  1249.         ld hl,(execcmd_pars)
  1250.         ld a,(hl)
  1251.         or a
  1252.         jp z,cmd_error_nopars
  1253.         xor a
  1254.         ld d,a
  1255. cmd_drop_par0
  1256.         add a,d
  1257.         ld e,a ;id
  1258.         add a,a
  1259.         add a,a
  1260.         add a,e
  1261.         add a,a
  1262.         ld d,a ;d=e*10
  1263.         ld a,(hl)
  1264.         inc hl
  1265.         sub '0'
  1266.         cp 10
  1267.         jr c,cmd_drop_par0
  1268.         ;e=id
  1269.         OS_DROPAPP
  1270.         or a
  1271.         ret z
  1272.         ld hl,twrongid
  1273.         jp cmderror
  1274.        
  1275. cmd_proc
  1276.         ld e,1 ;no id 0
  1277. cmd_proc0
  1278.         push de
  1279.         OS_GETAPPMAINPAGES ;d,e,h,l=pages in 0000,4000,8000,c000, c=flags
  1280.         or a
  1281.         jr nz,cmd_proc_skip
  1282.         ld a,d
  1283.         pop de
  1284.         push de
  1285.          push bc
  1286.         push af
  1287.         ex de,hl
  1288.         ld h,0
  1289.         call prword
  1290.         ld a,' '
  1291.         PRCHAR_
  1292.         pop af ;main page
  1293.         SETPG32KHIGH
  1294.          pop bc ;c=flags
  1295.          push bc
  1296.          bit factive,c
  1297.          ld a,'-'
  1298.          jr z,$+4
  1299.          ld a,'+'
  1300.          PRCHAR_
  1301.          pop bc
  1302.          push bc
  1303.          bit fgfx,c
  1304.          ld a,' '
  1305.          jr z,$+4
  1306.          ld a,'g'
  1307.          PRCHAR_
  1308.          pop bc
  1309.           bit fwaiting,c
  1310.           ld a,' '
  1311.           jr z,$+4
  1312.           ld a,'w'
  1313.           PRCHAR_
  1314.          ld a,' '
  1315.          PRCHAR_
  1316.         ld hl,0xc000+COMMANDLINE
  1317.         call prtext
  1318.         call prcrlf
  1319. cmd_proc_skip
  1320.         pop de
  1321.         inc e
  1322.         ld a,e
  1323.         inc a ;no id 0xff
  1324.         jr nz,cmd_proc0
  1325.         ret
  1326.  
  1327. cmd_date
  1328.         OS_GETTIME ;ix=date, hl=time
  1329.         call prdate_time
  1330.         jp prcrlf
  1331.        
  1332. cmd_t0
  1333.         ld a,(wordbuf)
  1334.         and 0xdf
  1335.         sub 'A'
  1336.         call cmdsetdrive
  1337.         or a
  1338.         ret z
  1339.         ld hl,tdrivenotfound
  1340.         jp cmderror
  1341.        
  1342. cmderror
  1343.         push hl
  1344.         ld de,_ERRORCOLOR
  1345.         SETCOLOR_
  1346.         pop hl
  1347.         call prtext
  1348.         ld de,_COLOR
  1349.         SETCOLOR_
  1350. prcrlf
  1351.         ;ld a,0x0d
  1352.         ;PRCHAR_
  1353.         ;ld a,0x0a
  1354.         ;PRCHAR_
  1355.         ld hl,crlfbuf
  1356.         ld de,2
  1357.         jp cmdprNchars
  1358. crlfbuf
  1359.         db 0x0d,0x0a
  1360.        
  1361. cmdsetdrive
  1362.         ld e,a
  1363.         OS_SETDRV
  1364.         ret
  1365.  
  1366. cmd_type
  1367.         ld hl,(execcmd_pars)
  1368.         ld a,(hl)
  1369.         or a
  1370.         jp z,cmd_error_nopars
  1371.         ld de,wordbuf
  1372.         call getword ;hl=terminator/space addr
  1373.  
  1374.         ld de,wordbuf ;de=drive/path/file
  1375.         OS_OPENHANDLE
  1376.         or a
  1377.         jp nz,cmd_error_wrongfile
  1378.         ld a,b
  1379.         ld (close_file1_handle),a
  1380.         ld hl,close_file1
  1381.         push hl
  1382.        
  1383. cmd_type0
  1384. ;B = file handle, DE = Buffer address, HL = Number of bytes to read
  1385.         push bc
  1386.         ld de,cmd_type_buf
  1387.         ld hl,1
  1388.         OS_READHANDLE
  1389. ;HL = Number of bytes actually read, A=error
  1390.         pop bc
  1391.         ld a,h
  1392.         or l
  1393.         ret z ;0 bytes remain
  1394.         push bc
  1395. cmd_type_buf=$+1
  1396.         ld a,0
  1397.         PRCHAR_
  1398.         pop bc
  1399.         jr cmd_type0
  1400.        
  1401. cmd_tee
  1402. ;tee filename
  1403. ;copy sdtin to filename and to stdout
  1404.         ld hl,(execcmd_pars)
  1405.         ld a,(hl)
  1406.         or a
  1407.         jp z,cmd_error_nopars
  1408.         ld de,wordbuf
  1409.         call getword ;hl=terminator/space addr
  1410.  
  1411.         ld de,wordbuf ;de=drive/path/file
  1412.         OS_CREATEHANDLE
  1413.         or a
  1414.         jp nz,cmd_error_wrongfile
  1415.         ld a,b
  1416.         ld (close_file1_handle),a
  1417.         ld hl,close_file1
  1418.         push hl
  1419.        
  1420. cmd_tee0
  1421.         push bc
  1422.         GETKEY_
  1423.         ld (cmd_type_buf),a
  1424.         pop bc
  1425.         ret c ;input pipe closed
  1426.         ld a,(cmd_type_buf)
  1427.         PRCHAR_
  1428. ;B = file handle, DE = Buffer address, HL = Number of bytes to read
  1429.         push bc
  1430.         ld de,cmd_type_buf
  1431.         ld hl,1 ;TODO набивать буфер, потом писать много
  1432.         OS_WRITEHANDLE
  1433. ;HL = Number of bytes actually written, A=error?
  1434.         pop bc
  1435.         jr cmd_tee0
  1436.        
  1437. cmd_echo
  1438.         ld hl,(execcmd_pars)
  1439.         call prtext
  1440.         jp prcrlf
  1441.        
  1442. cmd_pause
  1443.         call yieldgetkeyloop ;YIELDGETKEYLOOP
  1444.          cp key_redraw
  1445.          jr z,cmd_pause
  1446.         ret
  1447.  
  1448. cmd_copydir
  1449.         ld hl,(execcmd_pars)
  1450.         ld a,(hl)
  1451.         or a
  1452.         jp z,cmd_error_nopars
  1453.         ld de,wordbuf
  1454.         call getword ;hl=terminator/space addr
  1455.         call skipspaces
  1456.         ld a,(hl)
  1457.         or a
  1458.         jp z,cmd_error_notenoughpars
  1459.         ld de,wordbuf2
  1460.         call getword ;hl=terminator/space addr
  1461.  
  1462. cmd_copydir_go
  1463.         ld hl,wordbuf
  1464.         call prtext
  1465.         ld a,'>'
  1466.         PRCHAR_
  1467.         ld hl,wordbuf2
  1468.         call prtext
  1469.         call prcrlf
  1470.        
  1471.         ld de,wordbuf2
  1472.         OS_MKDIR
  1473.  
  1474.         ld bc,0 ;номер файла в директории
  1475. cmd_copydir0
  1476.         push bc
  1477.         ld de,cmdprompt
  1478.         OS_CHDIR
  1479.         ld de,wordbuf
  1480.         OS_CHDIR
  1481.         pop bc
  1482.         push bc
  1483.         call getdirfcb_bc
  1484.         pop bc
  1485.         ret nz ;jr nz,cmd_copydirq
  1486.  
  1487.         ld a,(fcb_filename)
  1488.         cp '.'
  1489.         jr z,cmd_copydir0_skip
  1490.         ld a,(fcb+FCB_FATTRIB)
  1491.         and FATTRIB_DIR
  1492.         jr nz,cmd_copydir0_recursive
  1493.        
  1494.         push bc
  1495.         ld hl,fcb_filename
  1496.         ld de,filenamebuf
  1497.         call cpmname_to_dotname
  1498.         call open_setdir2_create_copy
  1499.         pop bc
  1500. cmd_copydir0_skip
  1501.         inc bc
  1502.         jr cmd_copydir0
  1503.  
  1504.         macro STRPUSH
  1505. ;hl=string addr
  1506.         xor a
  1507.         push af
  1508.          ld a,(hl)
  1509.          inc hl
  1510.          or a
  1511.          push af
  1512.         jr nz,$-4
  1513.         pop af
  1514. ;в стеке лежит \0, текст (без терминатора)
  1515.         endm
  1516.        
  1517.         macro STRPOP
  1518. ;hl=string addr
  1519.         ld d,h
  1520.         ld e,l
  1521.          pop af
  1522.          ld (hl),a
  1523.          inc hl
  1524.          or a
  1525.         jr nz,$-4
  1526.         ex de,hl
  1527.         call strmirror
  1528.         endm
  1529.        
  1530. strmirror
  1531. ;hl=string addr
  1532.         ld d,h
  1533.         ld e,l
  1534.         call strlen
  1535.         ld b,h
  1536.         ld c,l
  1537.          ld a,b
  1538.          or c
  1539.          ret z
  1540. ;de=начало, bc=hl=длина
  1541.         ;ld h,b
  1542.         ;ld l,c
  1543.         add hl,de ;hl=конец+1
  1544.         srl b
  1545.         rr c ;bc=wid/2
  1546. mirrorbytes0
  1547.         dec hl
  1548.         ld a,(de)
  1549.         ldi
  1550.         dec hl
  1551.         ld (hl),a
  1552.         jp pe,mirrorbytes0
  1553.         ret
  1554.        
  1555. cmd_copydir0_recursive
  1556. ;recursive copydir <wordbuf>/<filename> <wordbuf2>/<filename>
  1557.         push bc
  1558.         ld hl,wordbuf
  1559.         STRPUSH
  1560.         ld hl,wordbuf2
  1561.         STRPUSH
  1562.         ;ld hl,cmdprompt
  1563.         ;STRPUSH
  1564.  
  1565.         ld hl,wordbuf
  1566.         ld bc,0
  1567.         xor a
  1568.         cpir
  1569.         dec hl ;hl=terminator addr
  1570.         ld (hl),'/'
  1571.         inc hl
  1572.         ex de,hl
  1573.         ld hl,fcb_filename
  1574.         ;ld de,filenamebuf
  1575.         call cpmname_to_dotname
  1576.        
  1577.         ld hl,wordbuf2
  1578.         ld bc,0
  1579.         xor a
  1580.         cpir
  1581.         dec hl ;hl=terminator addr
  1582.         ld (hl),'/'
  1583.         inc hl
  1584.         ex de,hl
  1585.         ld hl,fcb_filename
  1586.         ;ld de,filenamebuf
  1587.         call cpmname_to_dotname
  1588.        
  1589.         call cmd_copydir_go
  1590.  
  1591. ;restore dirnames, file #
  1592.         ;ld hl,cmdprompt
  1593.         ;STRPOP
  1594.         ld hl,wordbuf2
  1595.         STRPOP
  1596.         ld hl,wordbuf
  1597.         STRPOP
  1598.         pop bc
  1599.         jp cmd_copydir0_skip
  1600.        
  1601. open_setdir2_create_copy
  1602.         ;open....
  1603.         ld de,filenamebuf;wordbuf ;de=drive/path/file
  1604.         OS_OPENHANDLE
  1605.         or a
  1606.         jp nz,cmd_error_wrongfile
  1607.         ld a,b
  1608.         ld (close_file1_handle),a
  1609.         ld hl,close_file1
  1610.         push hl
  1611.  
  1612.         ;set dir2...
  1613.         ld de,cmdprompt
  1614.         OS_CHDIR
  1615.         ld de,wordbuf2
  1616.         OS_CHDIR
  1617.  
  1618.         ;create....
  1619.         ld de,filenamebuf;2;wordbuf2 ;de=drive/path/file
  1620.         OS_CREATEHANDLE
  1621.         or a
  1622.         jp nz,cmd_error_cant_copy
  1623.         ld a,b
  1624.         ld (cmd_copy_close_file2_handle),a
  1625.         ld hl,cmd_copy_close_file2
  1626.         push hl
  1627.  
  1628.         ;copy....
  1629.         jp cmd_copy0
  1630.        
  1631.        
  1632. getdirfcb_bc
  1633. ;bc=file number in current dir to read to fcb
  1634. ;nz=error
  1635.         push bc
  1636.         ld de,fcb
  1637.         OS_SETDTA
  1638.         ld de,fcbmask
  1639.         OS_FSEARCHFIRST ;de = pointer to unopened FCB (filename with ????????), read matching FCB to DTA
  1640.         pop bc
  1641.         or a
  1642.         ret nz
  1643.        
  1644. getdirfcb_bc0
  1645.         ld a,b
  1646.         or c
  1647.         ret z
  1648.         dec bc
  1649.         push bc
  1650.         ld de,fcb
  1651.         OS_SETDTA
  1652.         ld de,fcbmask
  1653.         OS_FSEARCHNEXT ;(NOT CP/M!!!)de = pointer to unopened FCB (filename with ????????), read matching FCB to DTA
  1654.         pop bc
  1655.         or a
  1656.         jr z,getdirfcb_bc0
  1657.         ret        
  1658.        
  1659. ;hl = poi to filename in string
  1660. findlastslash.
  1661. nfopenfnslash.
  1662.         ld d,h
  1663.         ld e,l ;de = after last slash
  1664. ;find last slash
  1665. nfopenfnslash0.
  1666.         ld a,[hl]
  1667.         inc hl
  1668.         or a
  1669.         jr z,nfopenfnslashq.
  1670.         cp '/'
  1671.         jr nz,nfopenfnslash0.
  1672.         jr nfopenfnslash.
  1673. nfopenfnslashq.
  1674. ;de = after last slash
  1675.         ret
  1676.  
  1677. commandslist
  1678.         dw cmd_dir
  1679.         db "ls",0
  1680.         dw cmd_dir
  1681.         db "dir",0
  1682.         dw cmd_del
  1683.         db "del",0
  1684.         dw cmd_del
  1685.         db "rm",0
  1686.         dw cmd_exit
  1687.         db "exit",0
  1688.         dw cmd_cd
  1689.         db "cd",0
  1690.         dw cmd_copy
  1691.         db "copy",0
  1692.         dw cmd_copy
  1693.         db "cp",0
  1694.         dw cmd_rem
  1695.         db "rem",0
  1696.         dw cmd_md
  1697.         db "md",0
  1698.         dw cmd_md
  1699.         db "mkdir",0
  1700.         dw cmd_ren
  1701.         db "ren",0
  1702.         dw cmd_ren
  1703.         db "mv",0
  1704.         dw cmd_mem
  1705.         db "mem",0
  1706.         dw cmd_mem
  1707.         db "free",0
  1708.         dw cmd_proc
  1709.         db "proc",0
  1710.         dw cmd_proc
  1711.         db "ps",0
  1712.         dw cmd_tee
  1713.         db "tee",0
  1714.         dw cmd_drop
  1715.         db "drop",0
  1716.         dw cmd_drop
  1717.         db "kill",0
  1718.         dw cmd_date
  1719.         db "date",0
  1720.         dw cmd_start
  1721.         db "start",0
  1722.         dw cmd_copydir
  1723.         db "copydir",0
  1724.         dw cmd_type
  1725.         db "type",0
  1726.         dw cmd_type
  1727.         db "cat",0
  1728.         dw cmd_echo
  1729.         db "echo",0
  1730.         dw cmd_pause
  1731.         db "pause",0
  1732.        
  1733.         dw -1 ;конец таблицы команд
  1734.  
  1735. tunknowncommand
  1736.         db "Unknown command",0
  1737. tdrivenotfound
  1738.         db "Drive not found",0
  1739. tnopars
  1740.         db "No parameters",0
  1741. tnotenoughpars
  1742.         db "Not enough parameters",0
  1743. tcantcopy
  1744.         db "Can't copy",0
  1745. tcantwrite
  1746.         db "Can't write",0
  1747. twrongpath
  1748.         db "Wrong path",0
  1749. twrongfile
  1750.         db "Wrong file",0
  1751. tcantmakedir
  1752.         db "Can't make the directory",0
  1753. tcantrename
  1754.         db "Can't rename",0
  1755. t_files_crlf
  1756.         db " files",0x0d,0x0a,0
  1757. tfree
  1758.         db "free pages=",0
  1759. twrongid
  1760.         db "Wrong ID",0
  1761.        
  1762. ;oldtimer
  1763. ;        dw 0
  1764.        
  1765.         db 0 ;для запарывания на случай отсутствия пути
  1766. wordbuf
  1767.         ds MAXCMDSZ+1
  1768. wordbuf2
  1769.         ds MAXCMDSZ+1
  1770. filenamebuf
  1771.         ds MAXCMDSZ+1
  1772. filenamebuf2
  1773.         ds MAXCMDSZ+1
  1774.  
  1775. fcb
  1776.         ds FCB_sz
  1777. fcb_filename=fcb+FCB_FNAME        
  1778.  
  1779. fcbmask
  1780.         db 0
  1781.         db "???????????"
  1782.         ds FCB_sz-11-1
  1783. fcbmask_filename=fcbmask+FCB_FNAME
  1784.  
  1785. fcb2
  1786.         ds FCB_sz
  1787. fcb2_filename=fcb2+FCB_FNAME        
  1788.  
  1789. fcb_bat
  1790.         ds FCB_sz
  1791. fcb_bat_filename=fcb_bat+FCB_FNAME        
  1792.  
  1793. oldpath ;TODO убрать (когда будет loadapp через OPENHANDLE)
  1794.         ds MAXPATH_sz;MAXCMDSZ+1
  1795.  
  1796. sysdir
  1797.         ds MAXPATH_sz
  1798.        
  1799. oldcmd
  1800.         ds MAXCMDSZ+1
  1801.        
  1802. copybuf
  1803.         ds 4096;128 ;можно сколько угодно
  1804. copybuf_sz=$-copybuf
  1805.  
  1806. params
  1807.         ds MAXCMDSZ+1
  1808.  
  1809. filinfo
  1810.         ds FILINFO_sz
  1811.  
  1812. emptypath
  1813.         db 0
  1814.  
  1815.         align 256
  1816. file_buf
  1817.         ds 128 ;buf for reading .bat
  1818. file_buf_end=$-1
  1819.  
  1820.         include "prdword.asm"
  1821.         include "cmdpr.asm"
  1822.         include "../_sdk/stdio.asm"
  1823.  
  1824. cmd_end
  1825.  
  1826.         ;display "cmd size ",/d,cmd_end-cmd_begin," bytes"
  1827.  
  1828.         savebin "cmd.com",cmd_begin,cmd_end-cmd_begin
  1829.        
  1830.         LABELSLIST "..\..\us\user.l"
  1831.