?login_element?

Subversion Repositories NedoOS

Rev

Rev 555 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. functionslist
  2.         dw func_rnd
  3.         db "$rnd",0
  4.        
  5.         dw -1 ;конец таблицы функций
  6.  
  7. getval_function
  8. ;hl'=text
  9.         call eatword
  10.         ld hl,functionslist ;list of internal commands
  11. getval_function0
  12.         ld c,(hl)
  13.         inc hl
  14.         ld b,(hl) ;адрес процедуры, соответствующей этой команде
  15.         inc hl
  16.         ld a,b
  17.         cp -1
  18.         jp z,fail_syntax ;ret z ;jr z,strcpexec_tryrun ;a!=0: no such internal command
  19.         ld de,wordbuf
  20.         push hl
  21.         call strcp
  22.         pop hl
  23.         jr nz,getval_function_fail
  24.         ld h,b
  25.         ld l,c
  26.         jp (hl) ;run internal command
  27. getval_function_fail
  28.         ld b,-1 ;чтобы точно найти терминатор
  29.         xor a
  30.         cpir ;найдём обязательно
  31.         jr getval_function0
  32.  
  33. commandslist
  34.         dw cmd_for
  35.         db "for",0
  36.         dw cmd_next
  37.         db "next",0
  38.        
  39.         dw cmd_clear
  40.         db "clear",0
  41.         dw cmd_new
  42.         db "new",0
  43.         dw cmd_quit
  44.         db "quit",0
  45.         dw cmd_run
  46.         db "run",0
  47.         dw cmd_goto
  48.         db "goto",0
  49.         dw cmd_edit
  50.         db "edit",0
  51.         dw cmd_list
  52.         db "list",0
  53.         dw cmd_save
  54.         db "save",0
  55.         dw cmd_savecode
  56.         db "savecode",0
  57.         dw cmd_load
  58.         db "load",0
  59.         dw cmd_loadcode
  60.         db "loadcode",0
  61.         dw cmd_system
  62.         db "system",0
  63.         dw cmd_pause
  64.         db "pause",0
  65.        
  66.         dw cmd_let
  67.         db "let",0
  68.         dw cmd_dim
  69.         db "dim",0
  70.         dw cmd_print
  71.         db "print",0
  72.         dw cmd_cls
  73.         db "cls",0
  74.         dw cmd_gfx
  75.         db "gfx",0
  76.         dw cmd_plot
  77.         db "plot",0
  78.         dw cmd_line
  79.         db "line",0
  80.        
  81.         dw cmd_if
  82.         db "if",0
  83.         dw cmd_then
  84.         db "then",0
  85.         dw cmd_colon
  86.         db ":",0
  87.         dw cmd_rem
  88.         db "rem",0
  89.        
  90.         dw -1 ;конец таблицы команд
  91.  
  92. docmd
  93. ;hl'=text
  94.         exx
  95.         push hl
  96.         ld a,(curgfx)
  97.         cp 6 ;textmode
  98.         jr z,docmd_nogfx
  99.         GET_KEY ;from BDOS
  100.         jr docmd_nogfxq
  101. docmd_nogfx
  102.         GETKEY_ ;from stdin
  103. docmd_nogfxq
  104.         pop hl
  105.         exx
  106.         cp key_esc
  107.         jp z,endbreak
  108.         call eatword
  109.         ld hl,commandslist ;list of internal commands
  110. strcpexec0
  111.         ld c,(hl)
  112.         inc hl
  113.         ld b,(hl) ;адрес процедуры, соответствующей этой команде
  114.         inc hl
  115.         ld a,b
  116.         cp -1
  117.         jp z,fail_syntax ;ret z ;jr z,strcpexec_tryrun ;a!=0: no such internal command
  118.         ld de,wordbuf
  119.         push hl
  120.         call strcp
  121.         pop hl
  122.         jr nz,strcpexec_fail
  123.         ld h,b
  124.         ld l,c
  125.         jp (hl) ;run internal command
  126. strcpexec_fail
  127.         ld b,-1 ;чтобы точно найти терминатор
  128.         xor a
  129.         cpir ;найдём обязательно
  130.         jr strcpexec0
  131.        
  132. eat
  133. ;hl'=курсор
  134.         exx
  135.         inc hl
  136.         call skipspaces
  137.         exx
  138.         ret
  139.  
  140. eatword
  141.         exx
  142.         ld de,wordbuf
  143.         call getword
  144.  ;Берем слово из (HL)-> wordbuf
  145.         call skipspaces
  146.  ; в (HL) пропускаем пробелы
  147.         exx
  148.         ret
  149.  
  150. eatclosebracket
  151.         exx
  152.         ld a,(hl)
  153.         exx
  154.         cp ')'
  155.         jp nz,fail_syntax
  156.         jp eat
  157.        
  158. eateq
  159.         exx
  160.         ld a,(hl)
  161.         exx
  162.         cp '='
  163.         jp nz,fail_syntax
  164.         jp eat
  165.        
  166. eatcomma
  167.         exx
  168.         ld a,(hl)
  169.         exx
  170.         cp ','
  171.         jp nz,fail_syntax
  172.         jp eat
  173.  
  174. cmd_pause
  175.         exx
  176.         push hl
  177.         ld a,(curgfx)
  178.         cp 6 ;textmode
  179.         jr z,cmd_pause_nogfx
  180.         YIELDGETKEYLOOP ;from BDOS
  181.         jr cmd_pause_nogfxq
  182. cmd_pause_nogfx
  183.         call yieldgetkeyloop ;from stdin
  184. cmd_pause_nogfxq
  185.         pop hl
  186.         exx
  187.         ret
  188.  
  189. cmd_gfx
  190.         call getexpr
  191.         exx
  192.         push hl
  193.         exx
  194.         ld a,e
  195.         and 7
  196.         ld e,a
  197.          ld (curgfx),a
  198.         OS_SETGFX
  199.         pop hl
  200.         exx
  201.         ret
  202.  
  203. getexprcolor
  204. ;out: a=color = %33210210
  205.         call getexpr
  206.         ld a,e
  207.         and 7
  208.         ld d,a
  209.         ld a,e
  210.         and 15
  211.         add a,a
  212.         add a,a
  213.         add a,a
  214.         or d ;%.3210210
  215.         rlca
  216.         rlca ;%210210.3, CY=3
  217.         rra  ;%3210210., CY=3
  218.         rra  ;%33210210
  219.         ret
  220.  
  221. cmd_line
  222. ;hl'=курсор
  223. ;line x2,y2,color
  224.         call getexpr
  225.         ld (cmd_line_x2),de
  226.         call eatcomma
  227.         call getexpr
  228.         ld (cmd_line_y2),de
  229.         call eatcomma
  230.         call getexprcolor ;a=color = %33210210
  231.  
  232.         push af ;color
  233.         call setpgs_scr
  234.         pop af ;color
  235.         ld bc,(cmd_plot_x)
  236.         ld de,(cmd_plot_y)
  237. cmd_line_x2=$+2
  238.         ld ix,0
  239.         ld (cmd_plot_x),ix
  240. cmd_line_y2=$+1
  241.         ld hl,0
  242.         ld (cmd_plot_y),hl
  243. ;bc=x (в плоскости экрана, но может быть отрицательным)
  244. ;de=y (в плоскости экрана, но может быть отрицательным)
  245. ;ix=x2
  246. ;hl=y2
  247. ;a=color = %332103210
  248.         exx
  249.         push hl
  250.         exx
  251.         call shapes_line
  252.         ;exx
  253.         pop hl
  254.         exx
  255.         jp restorebasicpages
  256.        
  257. cmd_plot
  258. ;hl'=курсор
  259. ;plot x,y,color
  260.         call getexpr
  261.         ld (cmd_plot_x),de
  262.         call eatcomma
  263.         call getexpr
  264.         ld (cmd_plot_y),de
  265.         call eatcomma
  266.         call getexprcolor
  267.         ;ld lx,a ;lx=color = %33210210
  268.         ld (prpixel_color_l),a
  269.         ld (prpixel_color_r),a
  270. cmd_plot_x=$+1
  271.         ld hl,0
  272.         ld bc,320
  273.         or a
  274.         sbc hl,bc
  275.         add hl,bc
  276.         ret nc
  277.         ex de,hl
  278.        
  279. cmd_plot_y=$+1
  280.         ld hl,0
  281.         ld bc,200
  282.         or a
  283.         sbc hl,bc
  284.         add hl,bc
  285.         ret nc
  286. ;l=y
  287.         call setpgs_scr
  288.          ld b,d
  289.          ld c,e
  290.         ld e,l
  291.         ld d,0
  292. ;bc=x ;de
  293. ;e=y ;c
  294. ;[lx=color = %33210210]
  295.         call prpixel
  296.         jp restorebasicpages
  297.  
  298. setpgs_scr
  299. ;setpgs_scr_low=$+1
  300.         ld a,(user_scr0_low) ;ok
  301.         SETPG32KLOW
  302. ;setpgs_scr_high=$+1
  303.         ld a,(user_scr0_high) ;ok
  304.         SETPG32KHIGH
  305.         ret
  306.  
  307.        
  308. scrbase=0x8000
  309. shapes_line
  310. ;bc=x (в плоскости экрана, но может быть отрицательным)
  311. ;de=y (в плоскости экрана, но может быть отрицательным)
  312. ;ix=x2
  313. ;hl=y2
  314. ;a=color = %332103210
  315.         ;ld (line_pixel_color),a
  316.         ld (prpixel_color_l),a
  317.         ld (prpixel_color_r),a
  318.         or a
  319.         sbc hl,de
  320.         add hl,de
  321.         jp p,shapes_line_noswap
  322.         ex de,hl ;y <-> y2
  323.         push ix
  324.         push bc
  325.         pop ix
  326.         pop bc ;x <-> x2
  327. shapes_line_noswap
  328.         or a
  329.         sbc hl,de ;dy >= 0
  330.         push hl ;dy
  331.         push ix
  332.         pop hl
  333.         sbc hl,bc
  334.         push hl ;dx
  335.         exx
  336.         pop bc ;dx
  337.         ld a,#03 ;inc bc
  338.         jp p,shapes_line_nodec
  339.         xor a
  340.         sub c
  341.         ld c,a
  342.         sbc a,b
  343.         sub c
  344.         ld b,a ;dx >= 0
  345.         ld a,#0b ;dec bc
  346. shapes_line_nodec
  347.         pop de ;dy
  348. ;a=код inc/dec bc
  349. ;bc'=x (в плоскости экрана, но может быть отрицательным)
  350. ;de'=y (в плоскости экрана, но может быть отрицательным)
  351. ;bc=dx
  352. ;de=dy
  353.         ex de,hl
  354.         or a
  355.         sbc hl,bc
  356.         add hl,bc
  357.         ex de,hl
  358.         jr nc,shapes_linever ;dy>=dx
  359.         ld hy,b
  360.         ld ly,c ;counter=dx
  361.         ;inc iy ;inc hy ;рисуем, включая последний пиксель (учтено в цикле)
  362.         ld h,b
  363.         ld l,c
  364.         sra h
  365.         rr l ;ym=dx div 2 ;TODO а если dx<0?
  366.          ;xor a
  367.          ;sub l
  368.          ;ld l,a
  369.          ;sbc a,h
  370.          ;sub l
  371.          ;ld h,a ;mym=256-(dx div 2)
  372.         exx
  373.         ld (shapes_lineincx),a
  374. ;bc=x
  375. ;de=y
  376. ;hl'=xm
  377. ;bc'=dx
  378. ;de'=dy
  379. shapes_linehor0
  380.         call line_pixel
  381. shapes_lineincx=$
  382.         inc bc ;x+1        
  383.         exx
  384.         ;add hl,de ;mym+dy
  385.         or a
  386.         sbc hl,de ;ym-dy
  387.         exx
  388.         jr nc,shapes_linehor1
  389.         inc de ;y+1
  390.         exx
  391.         ;or a
  392.         ;sbc hl,bc ;mym-dx
  393.         add hl,bc ;ym+dx
  394.         exx
  395. shapes_linehor1
  396.         dec iy
  397.         ld a,hy
  398.         rla
  399.         jp nc,shapes_linehor0
  400.         ret
  401. shapes_linever
  402.         ld hy,d
  403.         ld ly,e ;counter=dy
  404.         ;inc iy ;inc hy ;рисуем, включая последний пиксель (учтено в цикле)
  405.         ld h,d
  406.         ld l,e
  407.         sra h
  408.         rr l
  409.          ;xor a
  410.          ;sub l
  411.          ;ld l,a
  412.          ;sbc a,h
  413.          ;sub l
  414.          ;ld h,a ;mxm=256-(dy div 2)
  415.         exx
  416.         ld (shapes_lineincx2),a
  417. ;bc=x
  418. ;de=y
  419. ;hl'=xm
  420. ;bc'=dx
  421. ;de'=dy
  422. shapes_linever0
  423.         call line_pixel
  424.         inc de ;y+1
  425.         exx
  426.         ;add hl,bc ;mxm+dx
  427.         or a
  428.         sbc hl,bc ;xm-dx ;TODO а если dx<0?
  429.         exx
  430.         jr nc,shapes_linever1
  431. shapes_lineincx2=$
  432.         inc bc ;x+1
  433.         exx
  434.         ;or a
  435.         ;sbc hl,de ;mxm-dy
  436.         add hl,de ;xm+dy
  437.         exx
  438. shapes_linever1
  439.         dec iy
  440.         ld a,hy
  441.         rla
  442.         jp nc,shapes_linever0
  443.         ret
  444.  
  445. line_pixel
  446. ;bc=x (может быть отрицательным)
  447. ;de=y (может быть отрицательным)
  448.         ld hl,199
  449.         or a
  450.         sbc hl,de ;y
  451.         ret c ;y>199
  452.         ld hl,319
  453.         or a
  454.         sbc hl,bc ;x
  455.         ret c ;x>319
  456.         ;push bc
  457.         ;push de
  458. ;        push ix
  459.         ;ld a,e
  460.         ;ld d,b
  461.         ;ld e,c ;de=x
  462.         ;ld c,a ;c=y
  463. ;line_pixel_color=$+2
  464. ;        ld lx,0
  465. ;de=x (не портится)
  466. ;c=y (bc не портится)
  467. ;lx=color = %33210210
  468.         ;call prpixel
  469. ;        pop ix
  470.         ;pop de
  471.         ;pop bc
  472.         ;ret
  473. prpixel
  474. ;bc=x (не портится)
  475. ;e=y (de не портится)
  476. ;[lx=color = %33210210]
  477.        ;ld a,d
  478.         ld l,e
  479.         ;ld h,0
  480.         ;ld d,scrbase/256/8 ;h
  481.         ld h,scrbase/256/32
  482.         add hl,hl
  483.         add hl,hl
  484.         add hl,de
  485.         add hl,hl
  486.         add hl,hl
  487.         add hl,hl ;y*40 + scrbase
  488.        ;ld d,a
  489. prpixel_cury
  490. ;bc=x (не портится)
  491. ;hl=addr(y)
  492. ;lx=color = %33210210
  493.         ld a,b
  494.         rra
  495.         ld a,c
  496.         rra
  497.         jr c,prpixel_r
  498.         rra
  499.         jr nc,$+4
  500.         set 6,h
  501.         rra
  502.         jr nc,$+4
  503.         set 5,h
  504.         and %00111111
  505.         add a,l
  506.         ld l,a
  507.         adc a,h
  508.         sub l
  509.         ld h,a
  510. prpixel_color_l=$+1
  511.         ld a,0;lx
  512.         xor (hl)
  513.         and %01000111 ;keep left pixel
  514.         xor (hl) ;right pixel from screen
  515.         ld (hl),a
  516.         ret
  517. prpixel_r
  518.         rra
  519.         jr nc,$+4
  520.         set 6,h
  521.         rra
  522.         jr nc,$+4
  523.         set 5,h
  524.         and %00111111
  525.         add a,l
  526.         ld l,a
  527.         adc a,h
  528.         sub l
  529.         ld h,a
  530. prpixel_color_r=$+1
  531.         ld a,0;lx
  532.         xor (hl)
  533.         and %10111000 ;keep right pixel
  534.         xor (hl) ;left pixel from screen
  535.         ld (hl),a
  536.         ret
  537.  
  538. cmd_system
  539. ;hl'=курсор
  540. ;system "command params"
  541.         call getexpr
  542.         bit 7,c
  543.         jp z,fail_syntax
  544.         exx
  545.         push hl
  546.         exx
  547. ;hl = wordbuf = string
  548.  
  549.         ld de,curdir ;DE = Pointer to 64 byte (MAXPATH_sz!) buffer
  550.         OS_GETPATH
  551.         OS_SETSYSDRV ;TODO каталог cmd
  552.        
  553.         ld de,tcmd
  554.         OS_OPENHANDLE
  555.         or a
  556.         jp nz,fail_fo
  557.         ld a,b
  558.         ld (cmd_system_handle),a
  559.         OS_NEWAPP
  560.         or a
  561.         jp nz,close_restoredir_fail
  562. ;dehl=номера страниц в 0000,4000,8000,c000 нового приложения, b=id, a=error
  563.         push bc ;b=id
  564.        
  565.         ld a,d
  566.         SETPG32KHIGH
  567.         push de
  568.         push hl
  569.         ld hl,syscmdbuf
  570.         ld de,#c000+COMMANDLINE
  571.         ld bc,COMMANDLINE_sz
  572.         ldir ;command line
  573.         xor a
  574.         ld (#c000+COMMANDLINE+COMMANDLINE_sz-1),a ;на случай, если "cmd "+wordbuf больше 128 байт
  575.         pop hl
  576.         pop de
  577. cmd_system_handle=$+1
  578.         ld b,0
  579.         call readfile_pages_dehl
  580.         call cmd_system_close_restoredir
  581.  
  582.         pop af ;a=id
  583.         ld e,a
  584.         push de
  585.         OS_RUNAPP
  586.         pop de
  587.         WAITPID
  588.         pop hl
  589.         exx
  590.         ret
  591.        
  592. cmd_system_close_restoredir
  593.         ld a,(cmd_system_handle)
  594.         ld b,a
  595.         OS_CLOSEHANDLE
  596.         ld de,curdir
  597.         OS_CHDIR
  598.         jp restorebasicpages
  599.        
  600. close_restoredir_fail
  601.         call cmd_system_close_restoredir
  602.         jp fail_fo
  603.  
  604. popret
  605.         pop af
  606.         ret
  607. readfile_pages_dehl
  608.         ld a,d
  609.         push bc
  610.         SETPG32KHIGH
  611.         pop bc
  612.          ld a,e
  613.          push af
  614.         ld a,+(#c000+PROGSTART)/256
  615.         call cmd_loadpage
  616.         jr nz,popret
  617.          pop af ;e
  618.         call cmd_setpgloadpage
  619.         ret nz
  620.         ld a,h
  621.         call cmd_setpgloadpage
  622.         ret nz
  623.         ld a,l
  624. cmd_setpgloadpage
  625.         push bc
  626.         SETPG32KHIGH
  627.         pop bc
  628.         ld a,#c000/256
  629. cmd_loadpage
  630. ;a=loadaddr/256
  631. ;b=handle
  632. ;out: de=bytes read, NZ=end of file
  633. ;keeps hl,bc
  634.         push bc
  635.         push hl
  636.         ld d,a
  637.         ld e,0
  638.         ld hl,0
  639.         or a
  640.         sbc hl,de
  641. ;B = file handle, DE = Buffer address, HL = Number of bytes to read
  642.         push hl
  643.         OS_READHANDLE
  644. ;HL = Number of bytes actually read, A=error(=0)
  645.         ex de,hl
  646.         pop hl
  647.         or a
  648.         sbc hl,de ;Number of bytes to read - Number of bytes actually read
  649.         pop hl
  650.         pop bc
  651.         ret
  652.  
  653.  
  654. tcmd
  655.         db "cmd.com",0
  656.        
  657.        
  658. cmd_loadcode
  659. ;hl'=курсор
  660. ;load "name.bas"
  661.         call getexpr
  662.         bit 7,c
  663.         jp z,fail_syntax
  664.         call cmd_load_hl
  665. ;нельзя выходить по ret, потому что старая программа уничтожена
  666.         jp endofprog
  667.        
  668. cmd_load_hl
  669. ;hl = wordbuf = filename
  670.         ;exx
  671.         ;ld a,(hl)
  672.         ;exx
  673.         ;cp '"'
  674.         ;jp nz,fail
  675.         ;call readstr
  676.         ;jp c,fail
  677. ;wordbuf = filename
  678.         ;ld de,wordbuf ;de=drive/path/file
  679.         ex de,hl
  680.         OS_OPENHANDLE
  681. ;b=new file handle
  682.         or a
  683.         jp nz,fail_fo
  684.         ld de,progmem
  685.         ld hl,szprogmem
  686. ;B = file handle, DE = Buffer address, HL = Number of bytes to read
  687.         push bc
  688.         OS_READHANDLE
  689.         pop bc
  690. ;HL = Number of bytes actually read, A=error
  691.         ld de,progmem
  692.         add hl,de
  693.         ld (progend),hl
  694.         OS_CLOSEHANDLE        
  695.         call cmd_clear
  696.         ret
  697.  
  698. cmd_load
  699. ;hl'=курсор
  700. ;load "name.bas"
  701.         call getexpr
  702.         bit 7,c
  703.         jp z,fail_syntax
  704.         call cmd_load_text
  705. ;нельзя выходить по ret, потому что старая программа уничтожена
  706.         jp endofprog
  707.  
  708. cmd_load_text
  709. ;hl = wordbuf = filename
  710.         ;ld de,wordbuf ;de=drive/path/file
  711.         ex de,hl
  712.         OS_OPENHANDLE
  713. ;b=new file handle
  714.         or a
  715.         jp nz,fail_fo
  716.  
  717. read_next_str
  718.         ld de,cmdbuf
  719.         ld hl,1
  720. read_fsmb
  721. ;B = file handle, DE = Buffer address, HL = Number of bytes to read
  722.         push bc
  723.         push de
  724.         OS_READHANDLE
  725.         pop de
  726.         pop bc
  727.         ld a,l
  728.         or a
  729.         jp z,endfile ;Если не прочитали = конец файла - выходим
  730.         ld a,(de)
  731.         cp 0x0A
  732.         jp z,end_read ; Новая строка определяется по 0x0A
  733.         ld a,(de)
  734.         cp 0x0D
  735.         jp z,read_fsmb ; Просто проглатываем символ возврата каретки
  736.         inc de
  737.         jp read_fsmb
  738.  
  739. end_read
  740.         xor a
  741.         ld (de),a ;ставим терминатор в строку
  742.         ld hl,cmdbuf
  743.  
  744.         ex de,hl
  745.         ;or a
  746.         sbc hl,de ;вычисляем длину строки
  747.         jp z, read_next_str ; если пустая строка, читаем следующую
  748.         ex de,hl ;возвращаем на место hl=cmdbuf
  749.         push bc ; На всякий случай сохраняем file handle, мало ли чего...
  750.         call add_or_run_line
  751.         pop bc
  752.         jp read_next_str
  753.  
  754. endfile
  755.         OS_CLOSEHANDLE
  756.         ld hl,cmdbuf; иначе в командной строке последняя загруженная из файла команда
  757.         ld (hl),0
  758.         jp cmd_clear
  759.  
  760. cmd_savecode ; оригинальная процедура быстрой выгрузки программы в файл
  761. ;hl'=курсор
  762. ;save "name.bas"
  763.         call getexpr
  764.         bit 7,c
  765.         jp z,fail_syntax
  766.         ;exx
  767.         ;ld a,(hl)
  768.         ;exx
  769.         ;cp '"'
  770.         ;jp nz,fail
  771.         ;call readstr
  772.         ;jp c,fail
  773. ;wordbuf = filename
  774.         ;ld de,wordbuf ;de=drive/path/file
  775.         ex de,hl
  776.         OS_CREATEHANDLE
  777. ;b=new file handle
  778.         or a
  779.         jp nz,fail_fo
  780.         ld hl,(progend)
  781.         ld de,progmem
  782.         ;or a
  783.         sbc hl,de
  784. ;B = file handle, DE = Buffer address, HL = Number of bytes to write
  785.         push bc
  786.         OS_WRITEHANDLE
  787.         pop bc
  788.         OS_CLOSEHANDLE
  789.         ld hl,cmdbuf ; курсор на начало буфера
  790.         ld (hl),0
  791.         exx
  792.         ret
  793.  
  794. cmd_save
  795. ;hl'=курсор
  796. ;save "name.bas"
  797.         call getexpr
  798.         bit 7,c
  799.         jp z,fail_syntax
  800.         ex de,hl
  801. ;de=drive/path/file
  802.         OS_CREATEHANDLE
  803.         push bc ;filehandle
  804.         ;display cmd_save, " cmd_save"
  805.         ;display cmdbuf, " cmdbuf"
  806.        
  807. ;b=new file handle
  808.         or a
  809.         jp nz,fail_fo
  810. ;формат строк: номер строки(ст,мл), длина строки(мл,ст), строка(asciiz)
  811.         ld hl,progmem
  812. save_lines0
  813.         ld de,(progend)
  814.         or a
  815.         sbc hl,de
  816.         add hl,de
  817.         jr z,save_end
  818.        
  819.         push hl ;Проверка на нажатие брик
  820.         GETKEY_
  821.         pop hl
  822.         cp key_esc
  823.         jp z,endbreak
  824.  
  825.         ld d, (hl) ; загружаем в DE номер строки
  826.         inc hl
  827.         ld e, (hl)
  828.         inc hl
  829.  
  830.         push hl ; продолжение строки
  831.         push de ; номер в hex
  832.         ld hl,cmdbuf ; надо загрузить в hl' буфер куда положить уже текстовый номер строки
  833.         exx ; в hl' теперь номер
  834.         pop de ; номер в hex
  835.         call prlinenum_tomem ; hl' куда, de номер в hex
  836.         exx
  837.         ex hl,de ; de на продолжение cmdbuf
  838.         pop hl; продолжание строки
  839.  
  840.         ld a,' ' ; пробел
  841.         ld (de),a
  842.         inc de
  843.         ld c,(hl) ;длина строки
  844.         inc hl
  845.         ld b,(hl) ;длина строки
  846.         inc hl
  847.         ldir      ;копируем всю строку в de
  848.         ld a,0x0D
  849.         ld (de),a
  850.         inc de
  851.         ld a,0x0A
  852.         ld (de),a
  853.         inc de
  854.         inc hl; пропускаем терминатор
  855.  
  856.         pop bc ; достаем filehandle
  857.         push bc ;filehandle нам ещё пригодится
  858.         push hl ;там следующая строка
  859.         ld hl,cmdbuf
  860.         ex hl,de
  861.         sbc hl,de ; в hl длина получившейся текстовой строки
  862.         ld de,cmdbuf ; в de адрес самой строки
  863.  
  864. ;B = file handle, DE = Buffer address, HL = Number of bytes to write
  865.         OS_WRITEHANDLE
  866.         pop hl ; следующая строка
  867.         jr save_lines0
  868. save_end
  869.         pop bc
  870.         OS_CLOSEHANDLE
  871.         ld hl,cmdbuf
  872.         ld (hl),0 ; очищаем командную строку
  873.         exx ; hl' курсор на начало буфера
  874.         ret
  875.        
  876. cmd_new
  877.         ld hl,progmem
  878.         ld (progend),hl
  879.         call cmd_clear
  880.         jp endofprog
  881.  
  882. cmd_clear
  883.         ld hl,varmem
  884.         ld (varend),hl
  885.         ld hl,varindex_int
  886.         ld de,varindex_int+1
  887.         ld bc,511
  888.         ld (hl),l;0
  889.         ldir
  890.         ret
  891.        
  892. cmd_rem
  893.         jp gotonextline
  894.        
  895. cmd_for
  896. ;hl'=курсор
  897. ;for i=1 to 10 step 2
  898. ;параметры цикла (4+4(step)+4(to)+4(goto) байта)
  899.         exx
  900.         ld a,(hl)
  901.         exx
  902.         ld c,a ;имя
  903.         call eat
  904.        
  905.         ld a,c
  906.         call findvar_index
  907.         jr nz,cmd_for_nocreate
  908.         ld hl,(varend)
  909.         push hl
  910.         ld de,4*4
  911.         add hl,de
  912.         ld (varend),hl
  913.         pop de
  914. ;de=addr
  915.         ld h,varindex_int/256
  916.         ld l,c
  917.         ld (hl),e
  918.         inc h
  919.         ld (hl),d
  920. cmd_for_nocreate
  921.  
  922.         call eateq
  923.         push bc
  924.         call getexpr
  925.         pop bc
  926.         ld a,c
  927.         call setvar_int
  928.        
  929.         call eatword ;to
  930.        
  931.         push bc
  932.         call getexpr
  933.         pop bc
  934.         push hl ;HSW
  935.         push de ;LSW
  936.         ld a,c
  937.         call findvar_index
  938.         ld de,4+4
  939.         add hl,de
  940.         pop de ;LSW
  941.         ld (hl),e
  942.         inc hl
  943.         ld (hl),d
  944.         inc hl
  945.         pop de ;HSW
  946.         ld (hl),e
  947.         inc hl
  948.         ld (hl),d
  949.        
  950.         call eatword ;step
  951.        
  952.         push bc
  953.         call getexpr ;hlde=step
  954.         pop bc
  955.        
  956.         ld a,h
  957.         or l
  958.         or d
  959.         or e
  960.         jp z,fail_syntax
  961.                
  962.         push hl ;HSW
  963.         push de ;LSW
  964.         ld a,c
  965.         call findvar_index
  966.         ld de,4
  967.         add hl,de
  968.         pop de ;LSW
  969.         ld (hl),e
  970.         inc hl
  971.         ld (hl),d
  972.         inc hl
  973.         pop de ;HSW
  974.         ld (hl),e
  975.         inc hl
  976.         ld (hl),d
  977.        
  978.         ld a,c
  979.         call findvar_index
  980.         ld de,4+4+4
  981.         add hl,de
  982. ;currunline=$+1
  983.         ;ld de,0
  984.         ;inc de
  985.         exx
  986.         push hl
  987.         exx
  988.         pop de
  989.         ld (hl),e
  990.         inc hl
  991.         ld (hl),d
  992.         inc hl
  993.         ld (hl),0
  994.         inc hl
  995.         ld (hl),0
  996.  
  997.         ret
  998.        
  999. cmd_next
  1000. ;hl'=курсор
  1001. ;next i (i = i+step, if i<=to then goto...)
  1002.         exx
  1003.         ld a,(hl)
  1004.         exx
  1005.         ld c,a ;имя
  1006.         call eat
  1007.        
  1008.         ld a,c
  1009.         call findvar_index
  1010.         jp z,fail_syntax
  1011.        
  1012.         push hl
  1013.         ld e,(hl)
  1014.         inc hl
  1015.         ld d,(hl)
  1016.         inc hl
  1017.         ld c,(hl)
  1018.         inc hl
  1019.         ld b,(hl)
  1020.         inc hl ;bcde = i
  1021.        
  1022.         ld a,(hl)
  1023.         add a,e
  1024.         ld e,a
  1025.         inc hl
  1026.         ld a,(hl)
  1027.         adc a,d
  1028.         ld d,a
  1029.         inc hl
  1030.         ld a,(hl)
  1031.         adc a,c
  1032.         ld c,a
  1033.         inc hl
  1034.         ld a,(hl)
  1035.         adc a,b
  1036.         ld b,a ;bcde = i = i+step
  1037.        
  1038.         ex (sp),hl
  1039.         ld (hl),e
  1040.         inc hl
  1041.         ld (hl),d
  1042.         inc hl
  1043.         ld (hl),c
  1044.         inc hl
  1045.         ld (hl),b
  1046.         inc hl
  1047.         pop hl
  1048.        
  1049.         bit 7,(hl) ;step>=0?
  1050.         push af
  1051.         inc hl
  1052.        
  1053. ;to>=i?
  1054.         ld a,(hl)
  1055.         sub e
  1056.         ld e,a
  1057.         inc hl
  1058.         ld a,(hl)
  1059.         sbc a,d
  1060.         ld d,a
  1061.         inc hl
  1062.         ld a,(hl)
  1063.         sbc a,c
  1064.         ld c,a
  1065.         inc hl
  1066.         ld a,(hl)
  1067.         sbc a,b
  1068.         ld b,a
  1069.         inc hl
  1070. ;bcde = to-i
  1071. ;TODO знаковое переполнение
  1072.         pop af ;NZ = step<0
  1073.         call nz,negbcde
  1074. ;i<=to (to-i >= 0) - continue loop
  1075.         bit 7,b ;Z = to-i>=0
  1076.         ret nz ;end of loop
  1077.         call getint ;de=адрес после for ;было hlde=номер строки
  1078.         ex de,hl
  1079.         exx
  1080.         ret
  1081.         ;jp cmd_goto_ok
  1082.        
  1083. cmd_dim
  1084. ;hl'=курсор
  1085. ;dim a(15) - нумерация элементов с нуля
  1086.         exx
  1087.         ld a,(hl)
  1088.         exx
  1089.         ld c,a ;имя
  1090.         call eat
  1091.        
  1092.         ld a,c
  1093.         call findvar_array
  1094.         jp nz,fail_syntax ;уже есть такая переменная
  1095.  
  1096.         exx
  1097.         ld a,(hl)
  1098.         exx
  1099.         cp '('
  1100.         jp nz,fail_syntax
  1101.         call eat
  1102.         push bc
  1103.         call getexpr
  1104.         pop bc
  1105.         call eatclosebracket
  1106.        
  1107. ;hlde=de=size
  1108.  
  1109. ;c=name (char)
  1110.         ld hl,(varend)
  1111.         push hl
  1112.         ld (hl),e
  1113.         inc hl
  1114.         ld (hl),d
  1115.         inc hl
  1116.         add hl,de
  1117.         add hl,de
  1118.         add hl,de
  1119.         add hl,de
  1120.         ld (varend),hl
  1121.         pop de
  1122. ;de=addr
  1123.         ld h,varindex_int/256
  1124.         ld l,c
  1125.         ld (hl),e
  1126.         inc h
  1127.         ld (hl),d
  1128.         ret
  1129.        
  1130. cmd_edit
  1131. ;hl'=курсор
  1132.         call getexpr
  1133.         call findline
  1134.         ld a,(hl)
  1135.         cp d
  1136.         jp nz,fail_syntax
  1137.         inc hl
  1138.         ld a,(hl)
  1139.         cp e
  1140.         jp nz,fail_syntax
  1141.         ;hl=адрес строки, которую надо взять + 1
  1142.         inc hl
  1143.         inc hl
  1144.         inc hl
  1145.        
  1146.         push hl
  1147.         exx
  1148.         ld hl,cmdbuf
  1149.         exx
  1150.         call prlinenum_tomem
  1151.         exx
  1152.         ld (hl),' '
  1153.         inc hl
  1154.         push hl
  1155.         exx
  1156.         pop de ;cmdbuf+номер
  1157.         pop hl ;hl=адрес строки (текст)
  1158.        
  1159.         push hl
  1160.         call strlen
  1161.         ld b,h
  1162.         ld c,l
  1163.         inc bc ;длина с терминатором
  1164.         pop hl
  1165.        
  1166.         ;ld de,cmdbuf
  1167.         ;ld bc,MAXCMDSZ+1
  1168.         ldir
  1169.         jp endofedit
  1170.        
  1171. cmd_then
  1172. cmd_colon
  1173.         ret
  1174.        
  1175. cmd_list
  1176. ;номер строки(ст,мл), длина строки(мл,ст), строка(asciiz)
  1177.         ld hl,progmem ; progmem константа задающая начало памяти программы
  1178. list_lines0
  1179.         ld de,(progend) ; по адресу progend находится переменная указывающая на конец памяти программы
  1180.         or a
  1181.         sbc hl,de
  1182.         add hl,de
  1183.         ret z
  1184.        
  1185.         push hl ;Проверка на нажатие брик
  1186.         GETKEY_
  1187.         pop hl
  1188.         cp key_esc
  1189.         jp z,endbreak
  1190.  
  1191.         ld d,(hl)
  1192.         inc hl
  1193.         ld e,(hl) ;номер строки
  1194.         inc hl
  1195.         push hl
  1196.         call prword_de ;номер строки
  1197.         ld a,' '
  1198.         PRCHAR_
  1199.         pop hl
  1200.  
  1201.         ;ld e,(hl)
  1202.         inc hl
  1203.         ;ld d,(hl) ;длина строки
  1204.         inc hl
  1205.         call prtext ;hl after terminator
  1206.         call prcrlf
  1207.  
  1208.         jr list_lines0
  1209.        
  1210.        
  1211.         macro STRPUSH
  1212. ;hl=string addr
  1213.         xor a
  1214.         push af
  1215.          ld a,(hl)
  1216.          inc hl
  1217.          or a
  1218.          push af
  1219.         jr nz,$-4
  1220.         pop af
  1221. ;в стеке лежит \0, текст (без терминатора)
  1222.         endm
  1223.        
  1224.         macro STRPOP
  1225. ;hl=string addr
  1226.         ld d,h
  1227.         ld e,l
  1228.          pop af
  1229.          ld (hl),a
  1230.          inc hl
  1231.          or a
  1232.         jr nz,$-4
  1233.         ex de,hl
  1234.         call strmirror
  1235.         endm
  1236.        
  1237. strmirror
  1238. ;hl=string addr
  1239.         ld d,h
  1240.         ld e,l
  1241.         call strlen
  1242.         ld b,h
  1243.         ld c,l
  1244. ;de=начало, bc=hl=длина
  1245.         ;ld h,b
  1246.         ;ld l,c
  1247.         add hl,de ;hl=конец+1
  1248.         srl b
  1249.         rr c ;bc=wid/2
  1250. mirrorbytes0
  1251.         dec hl
  1252.         ld a,(de)
  1253.         ldi
  1254.         dec hl
  1255.         ld (hl),a
  1256.         jp pe,mirrorbytes0
  1257.         ret
  1258.        
  1259.  
  1260. cmd_let
  1261. ;hl'=курсор
  1262.         exx ;ld hl,(execcmd_pars)
  1263.         ld a,(hl)
  1264.         exx
  1265.         ld c,a
  1266.         exx
  1267.         inc hl ;call eat
  1268.         ld a,(hl)
  1269.         exx
  1270.         cp '$'
  1271.         jr z,cmd_let_str
  1272.         cp '('
  1273.         jr z,cmd_let_array
  1274. ;hl'=курсор
  1275.         call eatspaces
  1276.         call eateq
  1277.         ld a,c
  1278.         call findvar_int
  1279.         jr nz,cmd_let_createq
  1280.         ld a,c
  1281.         call addvar_int
  1282. cmd_let_createq
  1283.         push bc
  1284.         call getexpr ;hlde=value
  1285.         pop bc ;иначе выражение может запороть c
  1286.         ld a,c
  1287.         call setvar_int ;TODO не искать переменную второй раз
  1288.         ret
  1289.  
  1290. cmd_let_array
  1291.         call eat ;skip '(' and spaces
  1292.         push bc
  1293.         call getexpr
  1294.         pop bc
  1295.         call eatclosebracket
  1296.         ld a,c
  1297.         call findvar_int
  1298.         jp z,fail_syntax
  1299.         call indexarray
  1300.         push hl ;адрес элемента
  1301.         call eateq
  1302.         call getexpr ;hlde
  1303.         ld b,h
  1304.         ld c,l ;bcde
  1305.         pop hl ;адрес элемента
  1306.         ld (hl),e
  1307.         inc hl
  1308.         ld (hl),d
  1309.         inc hl
  1310.         ld (hl),c
  1311.         inc hl
  1312.         ld (hl),b
  1313.         ret
  1314.        
  1315. cmd_let_str
  1316.         call eat ;skip '$' and spaces
  1317.         exx
  1318.         ld a,(hl)
  1319.         exx
  1320.         cp '('
  1321.         jr z,cmd_let_strarray
  1322.         ld a,c
  1323.         call findvar_str
  1324.         jr nz,cmd_let_str_createq
  1325.         ld a,c
  1326.         call addvar_str
  1327. cmd_let_str_createq
  1328. ;hl'=курсор
  1329.         call eateq
  1330.         exx
  1331.         ld a,(hl)
  1332.         exx
  1333.         cp '"'
  1334.         jp nz,fail_syntax
  1335.        
  1336.         call readstr ;hl=str, hl'=after num and spaces, CY=error
  1337.         jp c,fail_syntax
  1338.        
  1339.         ;ld hl,wordbuf
  1340.         ;STRPUSH
  1341.        
  1342.         ;ld hl,wordbuf
  1343.         ld a,c
  1344.         call setvar_str
  1345.        
  1346.         ;ld hl,wordbuf
  1347.         ;STRPOP
  1348.        
  1349.         ret
  1350.  
  1351. cmd_let_strarray
  1352.         call eat ;skip '(' and spaces
  1353.         push bc
  1354.         call getexpr ;hlde=index
  1355.         pop bc
  1356.         call eatclosebracket
  1357.         call eateq
  1358.         ld a,c
  1359.         call findvar_str
  1360.         jp z,fail_syntax
  1361.         ld a,d
  1362.         or a
  1363.         jp nz,fail_syntax ;range check
  1364.         add hl,de
  1365.         push hl ;addr in str
  1366.         call getexpr ;hlde=char
  1367.         pop hl ;addr in str      
  1368.         ld (hl),e
  1369.         ret
  1370.        
  1371. cmd_cls
  1372.         exx
  1373.         push hl
  1374.         ld e,0;COLOR
  1375.         OS_CLS
  1376.         pop hl
  1377.         exx
  1378.         ret
  1379.  
  1380. cmd_if
  1381. ;hl'=курсор
  1382.         call getexpr
  1383.         ld a,h
  1384.         or l
  1385.         or d
  1386.         or e
  1387.         ret nz ;true = continue this line
  1388. gotonextline
  1389.         exx
  1390.         xor a
  1391.         ld bc,0
  1392.         cpir
  1393.         dec hl ;на терминаторе 
  1394.         ld a,(runmode)
  1395.         cp RUNMODE_PROG
  1396.         jr nz,gotonextlineq
  1397.         inc hl ;после строки
  1398.         call startline
  1399. gotonextlineq
  1400.         exx
  1401.         ret
  1402.        
  1403. cmd_goto
  1404. ;hl'=курсор
  1405.         call getexpr
  1406. cmd_goto_ok
  1407. ;hlde=номер строки
  1408.         call findline
  1409.         call startline
  1410.         exx
  1411.         ld a,RUNMODE_PROG
  1412.         ld (runmode),a
  1413.         ret
  1414.  
  1415.  
  1416. cmd_run
  1417. ;нельзя выходить по ret, потому что run могли вызвать из обработчика командной строки
  1418.         ld a,RUNMODE_PROG
  1419.         ld (runmode),a
  1420.         ld hl,progmem
  1421.         jr cmd_run_startline
  1422. cmd_run0
  1423. ;hl'=адрес строки
  1424.         exx
  1425.         ld a,(hl)
  1426.         or a
  1427.         jr nz,cmd_run_nonextline
  1428. runmode=$+1
  1429.         ld a,0
  1430.         cp RUNMODE_INTERACTIVE
  1431.         jp z,endofprog ;ret z ;end of line in interactive mode
  1432.         inc hl
  1433. cmd_run_startline
  1434.         call startline
  1435. cmd_run_nonextline
  1436.         exx
  1437.         call docmd
  1438.         jr cmd_run0
  1439.  
  1440. startline
  1441.         ld bc,(progend)
  1442.         or a
  1443.         sbc hl,bc
  1444.         add hl,bc
  1445.         jp nc,endofprog ;ret nc ;end of program
  1446.         ;ld d,(hl)
  1447.         inc hl
  1448.         ;ld e,(hl)
  1449.         inc hl
  1450.         ;ld (currunline),de
  1451.         ;ld e,(hl)
  1452.         inc hl
  1453.         ;ld d,(hl) ;line size
  1454.         inc hl
  1455.         ret
  1456.        
  1457. eatcolon
  1458. ;out: z=end of command
  1459.         exx
  1460.         ld a,(hl)
  1461.         exx
  1462.         or a
  1463.         ret z
  1464.         cp ':'
  1465.         ret nz
  1466.         call eat
  1467.         xor a ;Z
  1468.         ret
  1469.        
  1470. cmd_print
  1471. ;hl'=курсор
  1472.         call eatcolon
  1473.         jp z,prcrlf
  1474. cmd_print0
  1475.         exx
  1476.         ld a,(hl)
  1477.         exx
  1478.         cp ';'
  1479.         jp z,cmd_print_semicolon
  1480.         call getexpr
  1481.         call prval
  1482.         jr cmd_print
  1483. cmd_print_semicolon
  1484.         call eat
  1485.         call eatcolon
  1486.         jr nz,cmd_print ;TODO cmd_print0?
  1487.         ret
  1488.        
  1489. getexpr
  1490. ;out: hlde=value, c=type
  1491.         call getaddexpr
  1492. getexpr0
  1493.         exx
  1494.         ld a,(hl)
  1495.         exx
  1496.         ;cp ','
  1497.         ;ret z ;jp z,eat
  1498.         ;cp ')'
  1499.         ;ret z ;jp z,eat
  1500.         ;cp ':' ;call eatcolon
  1501.         ;ret z
  1502.         ;or a
  1503.         ;ret z
  1504.         cp '='
  1505.         jr z,getexpr_eq
  1506.         cp '>'
  1507.         jr z,getexpr_more
  1508.         cp '<'
  1509.         jr z,getexpr_less
  1510.         ret
  1511.        
  1512. getexpr_eq
  1513.         call eat
  1514.         call getexpr_eq_subr
  1515.         jr getexpr0
  1516.        
  1517. getexpr_more
  1518.         call eat
  1519.         exx
  1520.         ld a,(hl)
  1521.         exx
  1522.         cp '='
  1523.         jr z,getexpr_moreeq
  1524.         call getexpr_more_subr
  1525.         jr getexpr0
  1526.  
  1527. getexpr_less
  1528.         call eat
  1529.         exx
  1530.         ld a,(hl)
  1531.         exx
  1532.         cp '='
  1533.         jr z,getexpr_lesseq
  1534.         cp '>'
  1535.         jr z,getexpr_noteq
  1536.         call getexpr_less_subr
  1537.         jr getexpr0
  1538.        
  1539. getexpr_noteq
  1540.         call eat
  1541.         call getexpr_eq_subr
  1542.         call loginv
  1543.         jr getexpr0
  1544.  
  1545. getexpr_moreeq
  1546.         call eat
  1547.         call getexpr_less_subr
  1548.         call loginv
  1549.         jr getexpr0
  1550.  
  1551. getexpr_lesseq
  1552.         call eat
  1553.         call getexpr_more_subr
  1554.         call loginv
  1555.         jr getexpr0
  1556.  
  1557. getexpr_more_subr        
  1558. ;old > new: new-old = CY
  1559.         push bc
  1560.         push hl ;HSW
  1561.         push de ;LSW
  1562.         call getaddexpr
  1563.         pop bc ;LSW
  1564.         ex de,hl
  1565.         or a
  1566.         sbc hl,bc
  1567.         ex de,hl
  1568.         pop bc ;HSW
  1569.         sbc hl,bc
  1570.         pop bc
  1571.         ld hl,0
  1572.         ld de,0
  1573.         ret nc
  1574.         dec hl
  1575.         dec de ;old > new
  1576.         ret
  1577.        
  1578. getexpr_less_subr
  1579. ;old < new: old-new = CY
  1580.         push bc
  1581.         push hl ;old HSW
  1582.         push de ;old LSW
  1583.         call getaddexpr
  1584.         pop bc ;old LSW
  1585.         pop af ;old HSW
  1586.         push hl ;new HSW
  1587.         push de ;new LSW
  1588.         push af ;old HSW
  1589.         push bc ;old LSW
  1590.         pop de ;old LSW
  1591.         pop hl ;old HSW
  1592.        
  1593.         pop bc ;LSW
  1594.         ex de,hl
  1595.         or a
  1596.         sbc hl,bc
  1597.         ex de,hl
  1598.         pop bc ;HSW
  1599.         sbc hl,bc
  1600.         pop bc
  1601.         ld hl,0
  1602.         ld de,0
  1603.         ret nc
  1604.         dec hl
  1605.         dec de ;old < new
  1606.         ret
  1607.  
  1608. getexpr_eq_subr
  1609.         push bc
  1610.         push hl ;HSW
  1611.         push de ;LSW
  1612.         call getaddexpr
  1613.         pop bc ;LSW
  1614.         ex de,hl
  1615.         or a
  1616.         sbc hl,bc
  1617.         ex de,hl
  1618.         pop bc ;HSW
  1619.         sbc hl,bc
  1620.         ld a,d
  1621.         or e
  1622.         or h
  1623.         or l
  1624.         pop bc
  1625.         ld hl,0
  1626.         ld de,0
  1627.         ret nz
  1628.         dec hl
  1629.         dec de ;old = new
  1630.         ret
  1631.        
  1632. getaddexpr
  1633.         call getmulexpr
  1634. getaddexpr0
  1635.         exx
  1636.         ld a,(hl)
  1637.         exx
  1638.         ;or a
  1639.         ;ret z
  1640.         ;cp ')'
  1641.         ;ret z ;jp z,eat
  1642.         ;cp ','
  1643.         ;ret z ;jp z,eat
  1644.         ;cp ':' ;call eatcolon
  1645.         ;ret z
  1646.         cp '+'
  1647.         jr z,getaddexpr_plus
  1648.         cp '-'
  1649.         jr z,getaddexpr_minus
  1650.         ret
  1651.        
  1652. getaddexpr_plus
  1653.         call eat
  1654.         push bc
  1655.         push hl ;HSW
  1656.         push de ;LSW
  1657.         call getmulexpr
  1658.         pop bc ;LSW
  1659.         ex de,hl
  1660.         add hl,bc
  1661.         ex de,hl
  1662.         pop bc ;HSW
  1663.         adc hl,bc
  1664.         pop bc
  1665.         jr getaddexpr0
  1666.        
  1667. getaddexpr_minus
  1668.         call eat
  1669.         push bc
  1670.         push hl ;HSW
  1671.         push de ;LSW
  1672.         call getmulexpr
  1673.         pop bc ;LSW
  1674.         ex de,hl
  1675.         or a
  1676.         sbc hl,bc
  1677.         ex de,hl
  1678.         pop bc ;HSW
  1679.         sbc hl,bc
  1680.         call neghlde
  1681.         pop bc
  1682.         jr getaddexpr0
  1683.  
  1684. getmulexpr
  1685.         call getval_
  1686. getmulexpr0
  1687.         exx
  1688.         ld a,(hl)
  1689.         exx
  1690.         ;or a
  1691.         ;ret z
  1692.         ;cp ')'
  1693.         ;ret z ;jp z,eat
  1694.         ;cp ','
  1695.         ;ret z ;jp z,eat
  1696.         ;cp ':' ;call eatcolon
  1697.         ;ret z
  1698.         cp '*'
  1699.         jr z,getmulexpr_mul
  1700.         cp '/'
  1701.         jr z,getmulexpr_div
  1702.         ret
  1703.        
  1704. getmulexpr_div
  1705.         call eat
  1706.         push bc
  1707.         push hl ;HSW old
  1708.         push de ;LSW old
  1709.         call getval_
  1710.         push hl ;LSW new
  1711.         push de ;HSW new
  1712.         exx
  1713.         pop ix ;LSW new
  1714.         pop bc ;HSW new
  1715.         pop de ;LSW old
  1716.         ex (sp),hl ;pop hl ;HSW old
  1717.         call _DIVLONG.
  1718.         exx
  1719.         pop hl ;курсор
  1720.         exx
  1721.         pop bc
  1722.         jr getmulexpr0
  1723.  
  1724. getmulexpr_mul
  1725.         call eat
  1726.         push bc
  1727.         push hl ;HSW
  1728.         push de ;LSW
  1729.         call getval_
  1730.         pop ix ;LSW
  1731.         pop bc ;HSW
  1732.         call _MULLONG.
  1733.         pop bc
  1734.         jr getmulexpr0
  1735.        
  1736. ;hl, de / bc, ix
  1737. ;out: hl(high), de(low)
  1738. _DIVLONG.
  1739.         ;EXPORT _DIVLONG.
  1740.         ld a,h
  1741.         xor b
  1742.         push af
  1743.         xor b
  1744.         call m,neghlde
  1745.         ld a,b
  1746.         rla
  1747.         jr nc,divlongnonegbcix
  1748.         xor a
  1749.         sub lx
  1750.         ld lx,a
  1751.         ld a,0
  1752.         sbc a,hx
  1753.         ld hx,a
  1754.         ld a,0
  1755.         sbc a,c
  1756.         ld c,a
  1757.         ld a,0
  1758.         sbc a,b
  1759.         ld b,a
  1760. divlongnonegbcix
  1761. ;unsigned!!!
  1762. ;hl'hl,de'de <= hlde,bcix:
  1763.         push bc
  1764.         exx
  1765.         pop de ;de' = "bc_in"
  1766.         ld hl,0
  1767.         exx
  1768.         ld a,e
  1769.         ex af,af' ;e_in
  1770.         push de ;d_in
  1771.         ld c,l ;l_in
  1772.         ld a,h ;h_in
  1773.         ld hl,0
  1774.         push ix
  1775.         pop de ;de = "ix_in"
  1776.         ;a="h_in"
  1777. ;hl'hla <= 0000h_in
  1778.         call _DIVLONGP. ;"h"
  1779.         ld b,c ;"l_in"
  1780.         ld c,a ;"h"
  1781.         ld a,b ;a="l_in"
  1782. ;hl'hla <= 000hl_in
  1783.         call _DIVLONGP. ;"l"
  1784.         ld b,a ;"l"
  1785.         pop af ;a="d_in"
  1786.         push bc ;b="l"
  1787. ;hl'hla <= 00hld_in
  1788.         call _DIVLONGP. ;"d"
  1789.         ex af,af' ;a="e_in", a'="d"
  1790.         ;a="e_in"
  1791. ;hl'hla <= 0hlde_in
  1792.         call _DIVLONGP. ;"e"
  1793.         ld e,a ;"e"
  1794.         ex af,af' ;"d"
  1795.         ld d,a
  1796.         pop hl ;h="l"
  1797.         ld l,h
  1798.         ld h,c ;"h"
  1799.        
  1800.         pop af
  1801.         ret p
  1802.         jp neghlde
  1803. ;a = hl'hla/de'de
  1804. ;c not used
  1805. _DIVLONGP.
  1806. ;do 8 bits
  1807.         ld b,8
  1808. _DIVLONG0.
  1809. ;shift left hl'hla
  1810.         rla
  1811.         adc hl,hl
  1812.         exx
  1813.         adc hl,hl
  1814.         exx
  1815. ;no carry
  1816. ;try sub
  1817.         sbc hl,de
  1818.         exx
  1819.         sbc hl,de
  1820.         exx
  1821.         jr nc,$+2+1+1+2+1
  1822.         add hl,de
  1823.         exx
  1824.         adc hl,de
  1825.         exx
  1826. ;carry = inverted bit of result
  1827.         djnz _DIVLONG0.
  1828.         rla
  1829.         cpl
  1830.         ret
  1831.        
  1832. ;hl, de * bc, ix
  1833. ;out: hl(high), de(low)
  1834. _MULLONG.
  1835.         ;EXPORT _MULLONG.
  1836. ;signed mul is equal to unsigned mul
  1837. ;hlde*bcix = hlde*b000 + hlde*c00 + hlde*i0 + hlde*x
  1838.         ld a,lx
  1839.         push af ;lx
  1840.         push ix ;hx
  1841.         ld a,c
  1842.         push af ;c
  1843.         ld a,b
  1844. ;bcde <= hlde:
  1845.         ld b,h
  1846.         ld c,l
  1847. ;hlix <= 0
  1848.         ld hl,0
  1849.         ;ld ix,0
  1850.         push hl
  1851.         pop ix
  1852.         call _MULLONGP. ;hlix = (hlix<<8) + "b*hlde"
  1853.         pop af ;c
  1854.         call _MULLONGP. ;hlix = (hlix<<8) + "c*hlde"
  1855.         pop af ;hx
  1856.         call _MULLONGP. ;hlix = (hlix<<8) + "hx*hlde"
  1857.         pop af ;lx
  1858.         call _MULLONGP. ;hlix = (hlix<<8) + "lx*hlde"
  1859.         push ix
  1860.         pop de
  1861.         ret
  1862. ;hlix = (hlix<<8) + a*bcde
  1863. _MULLONGP.
  1864.         exx
  1865.         ld b,8
  1866. _MULLONG0.
  1867.         exx
  1868.         add ix,ix
  1869.         adc hl,hl
  1870.         rla
  1871.         jr nc,$+2+2+2
  1872.         add ix,de
  1873.         adc hl,bc
  1874.         exx
  1875.         djnz _MULLONG0. ;можно по a==0 (первый вход с scf:rla, далее add a,a)
  1876.         exx
  1877.         ret
  1878.  
  1879.  
  1880.        
  1881. getval_unaryminus
  1882.         call eat
  1883.         call getval_
  1884.         jp neghlde
  1885. getval_bracket
  1886.         call eat
  1887.         call getexpr
  1888.         jp eatclosebracket
  1889.        
  1890. getval_
  1891. ;hl'=курсор
  1892. ;out: hlde=value, c=type
  1893.         exx
  1894.         ld a,(hl)
  1895.         exx
  1896.         cp '$'
  1897.         jp z,getval_function
  1898.         cp '-'
  1899.         jr z,getval_unaryminus
  1900.         cp '('
  1901.         jr z,getval_bracket
  1902.         cp '"'
  1903.         jr z,getval_str
  1904.         sub '0'
  1905.         cp 10
  1906.         jr c,getval_num
  1907.         exx
  1908.         ld a,(hl)
  1909.         exx
  1910.         ld c,a ;name
  1911.         exx
  1912.         inc hl ;call eat
  1913.         ld a,(hl)
  1914.         exx
  1915.         cp '$'
  1916.         jr z,getval_varstr
  1917.         cp '('
  1918.         jr z,getval_vararray
  1919.         call eatspaces
  1920.         ld a,c
  1921.         call findvar_int
  1922.         jp z,fail_syntax
  1923.         ;ld a,c
  1924.         ;call getvar_int
  1925.         call getint
  1926.         res 7,c ;ld c,0 ;int
  1927.         ret
  1928. getval_varstr
  1929.         call eat ;skip '$' and spaces
  1930.         exx
  1931.         ld a,(hl)
  1932.         exx
  1933.         cp '('
  1934.         jr z,getval_varchararray        
  1935.         ld a,c
  1936.         call findvar_str
  1937.         jp z,fail_syntax
  1938.         ;ld a,c
  1939.         ;call getvar_str
  1940.         set 7,c ;ld c,128 ;str
  1941.         ret
  1942. getval_varchararray
  1943.         call eat
  1944.         push bc
  1945.         call getexpr
  1946.         pop bc
  1947.         call eatclosebracket
  1948.         ld a,c
  1949.         call findvar_str
  1950.         jp z,fail_syntax
  1951.         ld a,d
  1952.         or a
  1953.         jp nz,fail_syntax ;range check
  1954.         add hl,de
  1955.         ld e,(hl)
  1956.         ld hl,0
  1957.         ld d,h ;hlde=char
  1958.         res 7,c ;ld c,0 ;int
  1959.         ret
  1960. getval_vararray
  1961.         call eat
  1962.         push bc
  1963.         call getexpr
  1964.         pop bc
  1965.         call eatclosebracket
  1966.         ld a,c
  1967.         call findvar_array
  1968.         jp z,fail_syntax
  1969.         call indexarray
  1970.         call getint
  1971.         res 7,c ;ld c,0 ;int
  1972.         ret
  1973. getval_num
  1974.         call readnum ;hlde=num, hl'=after num and spaces, CY=error
  1975.         jp c,fail_syntax
  1976.         res 7,c ;ld c,0 ;int
  1977.         ret
  1978. getval_str
  1979.         call readstr ;hl=str, hl'=after str and spaces, CY=error
  1980.         jp c,fail_syntax
  1981.         set 7,c ;ld c,0 ;str
  1982.         ret
  1983.  
  1984. prval
  1985. ;hlde=value, c=type
  1986.         exx
  1987.         push hl
  1988.         exx
  1989.         bit 7,c
  1990.         jr nz,prval_str
  1991.         call prdword_hlde
  1992.         pop hl
  1993.         exx
  1994.         ret
  1995. prval_str
  1996.         call prstr_withlen
  1997.         pop hl
  1998.         exx
  1999.         ret
  2000.  
  2001.  
  2002. readstr
  2003. ;hl'=курсор (указывает на открывающую кавычку)
  2004. ;out: hl=str, hl'=after num and spaces, CY=error
  2005.         exx
  2006.         inc hl
  2007.         ld de,wordbuf
  2008. ;TODO проверка длины
  2009. quote_getword0
  2010.         ld a,(hl)
  2011.         or a
  2012.         ccf
  2013.         ret z ;CY=error
  2014.         ;jp z,fail ;jr z,quote_getwordq
  2015.         sub '"'
  2016.         jr z,quote_getwordq
  2017.         ldi
  2018.         jp quote_getword0
  2019. quote_getwordq
  2020.         xor a
  2021.         ld (de),a
  2022.         exx
  2023.         call eat ;съедаем кавычку и последующие пробелы
  2024.         ld hl,wordbuf
  2025.         or a ;NC = OK
  2026.         ret ;NC
  2027.  
  2028. indexarray
  2029. ;hl=адрес массива
  2030. ;de=индекс
  2031. ;c=имя массива?
  2032. ;out: hl=адрес элемента (fail, если out of bounds)
  2033.         push bc
  2034.         ld c,(hl)
  2035.         inc hl
  2036.         ld b,(hl)
  2037.         inc hl
  2038.         ex de,hl
  2039.         or a
  2040.         sbc hl,bc
  2041.         add hl,bc
  2042.         ex de,hl
  2043.         pop bc
  2044.         jp nc,fail_syntax ;range check
  2045.         add hl,de
  2046.         add hl,de
  2047.         add hl,de
  2048.         add hl,de
  2049.         ret
  2050.  
  2051. func_rnd
  2052. ;Patrik Rak
  2053. rndseed1=$+1
  2054.         ld  hl,0xA280   ; xz -> yw
  2055. rndseed2=$+1
  2056.         ld  de,0xC0DE   ; yw -> zt
  2057.         ld  (rndseed1),de  ; x = y, z = w
  2058.         ld  a,e         ; w = w ^ ( w << 3 )
  2059.         add a,a
  2060.         add a,a
  2061.         add a,a
  2062.         xor e
  2063.         ld  e,a
  2064.         ld  a,h         ; t = x ^ (x << 1)
  2065.         add a,a
  2066.         xor h
  2067.         ld  d,a
  2068.         rra             ; t = t ^ (t >> 1) ^ w
  2069.         xor d
  2070.         xor e
  2071.         ld  h,l         ; y = z
  2072.         ld  l,a         ; w = t
  2073.         ld  (rndseed2),hl
  2074.         ex de,hl
  2075.         ld hl,0
  2076.         res 7,c ;int
  2077.         ret
  2078.