?login_element?

Subversion Repositories NedoOS

Rev

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

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