Subversion Repositories NedoOS

Rev

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