Login

Subversion Repositories NedoOS

Rev

Rev 1486 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

        DEVICE ZXSPECTRUM128
        include "../_sdk/sys_h.asm"

MAXCMDSZ=COMMANDLINE_sz-1;127 ;не считая терминатора
;txtscrhgt=25
txtscrwid=80
CMDLINEY=24

_COLOR=0x0007;7
_ERRORCOLOR=0x0009;0x42

        macro asmgetchar
        ld a,(de)
        endm
       
        macro asmnextchar
        inc de
        endm

       macro MATCH_NOEAT s1
        cp s1
        ret nz
       endm
       macro MATCH_NOGET s1
        cp s1
        ret nz
        asmnextchar ;eat
       endm
       macro MATCH s1
        MATCH_NOGET s1
        asmgetchar
       endm

       macro skipspaces
        call asmskipspaces
       endm

        org PROGSTART
cmd_begin
        ld sp,0x4000 ;не должен опускаться ниже 0x3b00! иначе возможна порча OS        
        call initstdio

        OS_GETMAINPAGES
;dehl=номера страниц в 0000,4000,8000,c000
        push hl
        OS_DELPAGE
        pop hl
        push hl
        ld e,h
        OS_DELPAGE
        pop hl
        ld e,l
        OS_DELPAGE
       
cmdmainloop
        call editcmd
        call prcrlf
       
        ld hl,cmdbuf
        ld de,oldcmd
        ld bc,MAXCMDSZ+1
        ldir

        ld hl,xnumstack
        ld (xnumstacktop),hl

        ld de,cmdbuf
        asmgetchar
;TODO определить тип команды (присваивание, вызов, ветвление)
        call matchexpr

        ld de,xnum1
        call popxnum
        ld hl,xnum1
        ld de,xOP1
        call mov10 ;без этого почему-то не работает
        ld hl,xOP1 ;куда печатаем?
         ld bc,xOP1 ;что печатаем?
        call xtostr ;превращает число в строку
       push hl
        ;ld hl,strout-1
        ld c,0
        call prtext
        call prcrlf
       pop hl
       ld de,cmdbuf
       call strcopy
        xor a
        ;ld (cmdbuf),a
        ld (curcmdscroll),a
        jp cmdmainloop

cmd_exit
lastresult=$+1
       ld hl,0
        QUIT

;;;;;;;;;;;;;;;;;;
       
editcmd_up
        xor a
        ld (curcmdscroll),a
        ld de,cmdbuf
        ld hl,oldcmd
        ld bc,MAXCMDSZ+1
        ldir
        ;jp editcmd

editcmd
        ld hl,cmdbuf
        call strlen
        ld a,l
        ld (curcmdx),a
editcmd0
        call fixscroll_prcmd
        call cmdcalccurxy
        SETX_;SETXY_
        ;ld e,CURSORCOLOR;0x38
        ;OS_PRATTR ;нарисовать курсор
        call yieldgetkeyloop ;YIELDGETKEYLOOP
         ;ld a,c ;keynolang
        ;push af
        ;call cmdcalccurxy
        ;SETXY_
        ;ld e,COLOR;7
        ;OS_PRATTR ;стереть курсор
        ;pop af
        cp key_enter
        ret z
        cp key_up
        jr z,editcmd_up
         ld hl,editcmd0
         push hl
        ;ld hl,cmdbuf
        cp key_backspace
        jr z,editcmd_backspace
        cp key_left
        jr z,editcmd_left
        cp key_right
        jr z,editcmd_right
        cp key_home
        jr z,editcmd_home
        cp key_end
        jr z,editcmd_end
        cp key_del
        jr z,editcmd_del
        cp 0x20
        ret c ;jr c,editcmdok ;прочие системные кнопки не нужны
;type in
editcmdtypein
        ld e,a
        ld hl,cmdbuf
        call strlen ;hl=length
        ld bc,MAXCMDSZ
        or a
        sbc hl,bc
        ret nc ;jr nc,editcmdok ;некуда вводить
        call cmdcalctextaddr ;hl=addr, a=curcmdx
        inc a
        ld (curcmdx),a
        jp strinsch ;e=ch
       
editcmd_backspace
        call cmdcalctextaddr ;hl=addr, a=curcmdx
        or a
        ret z ;jr z,editcmdok ;нечего удалять
        dec a
        ld (curcmdx),a
        jp strdelch ;удаляет предыдущий символ
     
editcmd_del
        call cmdcalctextaddr ;hl=addr, a=curcmdx
        inc hl
        jp strdelch ;удаляет предыдущий символ
     
editcmd_left
        ld a,(curcmdx)
        or a
        ret z ;jr z,editcmdok ;некуда влево
        dec a
editcmd_leftq
        ld (curcmdx),a
        ret
editcmd_home
        xor a
        jr editcmd_leftq
editcmd_end
        ld hl,cmdbuf
        call strlen ;hl=length
        ld a,l
        jr editcmd_leftq

editcmd_right
        call cmdcalctextaddr ;hl=addr, a=curcmdx
        inc (hl)
        dec (hl)
        ret z ;jr z,editcmdok ;некуда право, стоим на терминаторе
        inc a
        ld (curcmdx),a
        ret

execcmd
;a=next char
execcmd0
        ld hl,commandslist ;list of internal commands
strcpexec0
        ld c,(hl)
        inc hl
        ld b,(hl)
        inc hl
       inc b
        jr z,execcmderr
       dec b
       push af
       push de
        ld de,wordbuf
        push hl
        call strcp
        pop hl
        jr nz,strcpexec_fail
       pop de
       pop af
       cp a ;z=no error
        ld h,b
        ld l,c
        jp (hl) ;run internal command
strcpexec_fail
        ld b,-1 ;чтобы точно найти терминатор
        xor a
        cpir ;найдём обязательно
       pop de
       pop af
        jr strcpexec0

execcmderr
        or a
        ret nz ;nz=error
        cp 1
        ret ;nz=error

;;;;;;;;;;;;;;;;

matchexpr
;a=char (двигает курсор до первого символа, не годящегося для вычисления выражения, возвращает его в a)
;out: bc=result
        call matchmulexpr
        ret nz ;error
matchexpr_loop
;TODO << >> || ^^ == != < > <= >=
        cp '-'
        jr z,matchexpr_minus
        cp '+'
        jr z,matchexpr_plus
        ;cp '|'
        ;jr z,matchexpr_or
        ;cp '^'
        ;jr z,matchexpr_xor
        cp a
        ret ;z=no error (end of expr)
matchexpr_minus
        call compilepushold
        asmnextchar ;eat
        asmgetchar
        call matchmulexpr
        ret nz ;error
        call compilesuboldnew
        jr matchexpr_loop
matchexpr_plus
        call compilepushold
        asmnextchar ;eat
        asmgetchar
        call matchmulexpr
        ret nz ;error
        call compileaddnewold
        jr matchexpr_loop

matchmulexpr
;a=char (двигает курсор до первого символа, не годящегося для вычисления выражения, возвращает его в a)
;out: bc=result
        call matchval
        ret nz ;error
matchmulexpr_loop
;TODO &&
        cp '*'
        jr z,matchmulexpr_mul
        cp '/'
        jr z,matchmulexpr_div
        ;cp '&'
        ;jr z,matchmulexpr_and
        cp a
        ret ;z=no error (end of expr)
matchmulexpr_mul
        call compilepushold
        asmnextchar ;eat
        asmgetchar
        call matchval
        ret nz ;error
        call compilemulnewold
        jr matchmulexpr_loop
matchmulexpr_div
        call compilepushold
        asmnextchar ;eat
        asmgetchar
        call matchval
        ret nz ;error
        call compiledivoldnew
        jr matchmulexpr_loop

matchval_plus
        asmnextchar ;eat
        asmgetchar
matchval
;nnn
;var ;TODO labels
;(expr)
;-val
;+val
        cp '-'
        jp z,matchval_minus
        cp '('
        jp z,matchval_bracket
        cp '#'
        jp z,matchval_hex
        cp '+'
        jp z,matchval_plus
        cp '.'
        jp z,matchdec
        sub '0'
        cp 10
        jp nc,matchval_nodigit
        add a,'0'
matchdec
        ld hl,wordbuf
matchdec0
        ld (hl),a
        inc hl
        asmnextchar
        asmgetchar
        cp '.'
        jr z,matchdec0
        cp '0'
        jr c,matchdec0q
        cp '0'+10
        jr c,matchdec0
matchdec0q
        cp 'e'
        jr nz,matchdecnoexp
        ld (hl),a
        inc hl
        asmnextchar
        asmgetchar
        cp '-'
        jr nz,matchdecnoexpminus
       if 0
;либа не переваривает отрицательную экспоненту, поэтому делаем n*pow10(exp)
        call matchdecnoexp
        call matchval
       push af
       push de
        ld de,xnum1
        call popxnum
        ld hl,xnum1
        ld bc,xOP1
        call xpow10
        ld de,xnum1
        call popxnum
        ld hl,xOP1
        ld de,xnum1
        ld bc,xnum2
        call xmul
        ld hl,xnum2
        call pushxnum
       pop de
       pop af
        ld (hl),0
        cp a ;z
        ret
       else
        ld (hl),a
        inc hl
        asmnextchar
        asmgetchar
       endif
matchdecnoexpminus
        sub '0'
        cp 10
        jr nc,matchval_nodigit
        add a,'0'
matchdec1
        ld (hl),a
        inc hl
        asmnextchar
        asmgetchar
        cp '0'
        jr c,matchdec1q
        cp '0'+10
        jr c,matchdec1
matchdec1q
matchdecnoexp
        ld (hl),0
       push af
       push de
        ld hl,wordbuf
        ld bc,xnum1
        call strtox ;превращает строку в число
        ld hl,xnum1
        call pushxnum
       pop de
       pop af
        cp a ;z
        ret
matchval_nodigit
        add a,'0' ;как было (для следующих match)
        ld hl,wordbuf
matchword0
        ld (hl),a
        inc hl
        asmnextchar
        asmgetchar
        cp 'a'
        jr c,matchword0q
        cp 'z'+1
        jr c,matchword0
matchword0q
        ld (hl),0
        jp execcmd

matchval_hex
        asmnextchar ;eat
        asmgetchar
        ld bc,0
matchval_hex0
        sub '0'+10
        cp -10
        jr c,matchval_hex_nodigit
matchval_hex_add
        add a,10
       dup 4
        sla c
        rl b
       edup
        or c
        ld c,a
        asmnextchar ;eat
        asmgetchar
        jr matchval_hex0
matchval_hex_nodigit
        sub 'a'-('0'+10)
        cp 6
        jr c,matchval_hex_add
        sub 'A'-'a'
        cp 6
        jr c,matchval_hex_add
        ;sub -'A' ;как было
       call compilenum_bc
        asmgetchar
        cp a ;z
        ret

matchval_minus
        asmnextchar ;eat
        asmgetchar
        call matchval
        ret nz
       call compileneg
        asmgetchar
        cp a ;z
        ret

matchval_bracket
        asmnextchar ;eat
        asmgetchar
        call matchexpr
        ret nz
        MATCH ')'
        ret

compilenum_bc
       push af
       push de
        ld h,b
        ld l,c
        ld bc,xnum1
        call i16tox ; Converts the 16-bit signed integer in HL to an extended precision float at BC ;TODO u64tox
        ld hl,xnum1
        call pushxnum
       pop de
       pop af
        ret

compilepushold
       push af
       push de
        ld de,xnum1
        call popxnum
        ld hl,xnum1
        call pushxnum
        ld hl,xnum1
        call pushxnum
       pop de
       pop af
        ret

compileaddnewold
       push af
       push de
        ld de,xnum1
        call popxnum
        ld de,xnum2
        call popxnum
        ld hl,xnum2
        ld de,xnum1
        ld bc,xOP1
        call xadd
        ld hl,xOP1
        call pushxnum
       pop de
       pop af
        ret

compilesuboldnew
       push af
       push de
        ld de,xnum1
        call popxnum
        ld de,xnum2
        call popxnum
        ld hl,xnum2
        ld de,xnum1
        ld bc,xOP1
        call xsub
        ld hl,xOP1
        call pushxnum
       pop de
       pop af
        ret

compilemulnewold
       push af
       push de
        ld de,xnum1
        call popxnum
        ld de,xnum2
        call popxnum
        ld hl,xnum2
        ld de,xnum1
        ld bc,xOP1
        call xmul
        ld hl,xOP1
        call pushxnum
       pop de
       pop af
        ret

compiledivoldnew
       push af
       push de
        ld de,xnum1
        call popxnum
        ld de,xnum2
        call popxnum
        ld hl,xnum2
        ld de,xnum1
        ld bc,xOP1
        call xdiv
        ld hl,xOP1
        call pushxnum
       pop de
       pop af
        ret

compileneg
       push af
       push de
        ld de,xnum1
        call popxnum
        ld hl,xnum1
        ld bc,xOP1
        call xneg
        ld hl,xOP1
        call pushxnum
       pop de
       pop af
        ret

cmd_e
        ld hl,xconst_e
        jr cmd_const
cmd_pi
        ld hl,xconst_pi
        jr cmd_const
cmd_const
       push af
       push de
        call pushxnum
       pop de
       pop af
        ret

cmd_sin
        ld hl,xsin
        jr cmd_onepar
cmd_cos
        ld hl,xcos
        jr cmd_onepar
cmd_tan
        ld hl,xtan
        jr cmd_onepar
cmd_sinh
        ld hl,xsinh
        jr cmd_onepar
cmd_cosh
        ld hl,xcosh
        jr cmd_onepar
cmd_tanh
        ld hl,xtanh
        jr cmd_onepar
cmd_asin
        ld hl,xasin
        jr cmd_onepar
cmd_acos
        ld hl,xacos
        jr cmd_onepar
cmd_atan
        ld hl,xatan
        jr cmd_onepar
cmd_asinh
        ld hl,xasinh
        jr cmd_onepar
cmd_acosh
        ld hl,xacosh
        jr cmd_onepar
cmd_atanh
        ld hl,xatanh
        jr cmd_onepar
cmd_abs
        ld hl,xabs
        jr cmd_onepar
cmd_ln
        ld hl,xln
        jr cmd_onepar
cmd_exp
        ld hl,xexp
        jr cmd_onepar
cmd_sqrt
        ld hl,xsqrt
        jr cmd_onepar

cmd_onepar
;a=next char
;hl=xcmd
       push hl
        skipspaces
        call matchval
       pop hl
        ld (cmd_onepar_xcmd),hl
       push af
       push de
        ld de,xnum1
        call popxnum
        ld hl,xnum1
        ld bc,xOP1
cmd_onepar_xcmd=$+1
        call xsqrt
        ld hl,xOP1
        call pushxnum
       pop de
       pop af
        ret

;out: nz (error) if eol ;остаётся на первом непробеле и его возвращает в a
asmskipspaces_next
        asmnextchar
        asmgetchar
asmskipspaces
        cp 9 ;tab
        jr z,asmskipspaces_next
        cp ' '
        jr z,asmskipspaces_next
        ret c ;error (nz)
        cp a ;z
        ret

;;;;;;;;;;;;;;

pushxnum
;hl=xnum to push
xnumstacktop=$+1
        ld de,xnumstack
        ld bc,10
        ldir
        ld (xnumstacktop),de
        ret
popxnum
;de=xnum buf to pop
        ld hl,(xnumstacktop)
        ld bc,-10
        add hl,bc
        ld (xnumstacktop),hl
        ld bc,10
        ldir
        ret

cmderror
        push hl
        ld de,_ERRORCOLOR
        SETCOLOR_
        pop hl
        call prtext
        ld de,_COLOR
        SETCOLOR_
prcrlf
        ;ld a,0x0d
        ;PRCHAR_
        ;ld a,0x0a
        ;PRCHAR_
        ld hl,crlfbuf
        ld de,2
        jp cmdprNchars
crlfbuf
        db 0x0d,0x0a

commandslist
        dw cmd_e
        db "e",0
        dw cmd_pi
        db "pi",0
        dw cmd_abs
        db "abs",0
        dw cmd_asin
        db "asin",0
        dw cmd_acos
        db "acos",0
        dw cmd_atan
        db "atan",0
        dw cmd_asinh
        db "asinh",0
        dw cmd_acosh
        db "acosh",0
        dw cmd_atanh
        db "atanh",0
        dw cmd_sin
        db "sin",0
        dw cmd_cos
        db "cos",0
        dw cmd_tan
        db "tan",0
        dw cmd_sinh
        db "sinh",0
        dw cmd_cosh
        db "cosh",0
        dw cmd_tanh
        db "tanh",0
        dw cmd_exp
        db "exp",0
        dw cmd_ln
        db "ln",0
        dw cmd_sqrt
        db "sqrt",0
       
        dw -1 ;конец таблицы команд

tunknowncommand
        db "Unknown command",0


        include "str.asm"
        include "cmdpr.asm"
        include "../_sdk/stdio.asm"

xOP1; = 8000h
        ds 182 ;162 for atan,182 for xlog
xOP2 = xOP1+10
xOP3 = xOP1+20
xOP4 = xOP1+30
xOP5 = xOP1+40
seed0=80F8h
seed1=80FCh

; Defines
;#define addx(o1,o2,d) ld hl,o1 \ ld de,o2 \ ld bc,d \ call xadd
;#define subx(o1,o2,d) ld hl,o1 \ ld de,o2 \ ld bc,d \ call xsub
;#define rsubx(o1,o2,d) ld hl,o1 \ ld de,o2 \ ld bc,d \ call xrsub
;#define mulx(o1,o2,d) ld hl,o1 \ ld de,o2 \ ld bc,d \ call xmul
;#define divx(o1,o2,d) ld hl,o1 \ ld de,o2 \ ld bc,d \ call xdiv
;#define sqrtx(o1,d) ld hl,o1 \ ld bc,d \ call xsqrt
;#define strx(o1,d) ld hl,o1 \ ld bc,d \ call xtostr
;#define movx(src,dest)  ld hl,src \ ld de,dest \ call mov10

; Macros
        macro dec_hl_opt x
        if ((x)&255)>0
  dec l
        else
  dec hl
        endif
        endm

        macro inc_hl_opt x
        if ((x)&255)<255
  inc l
        else
  inc hl
        endif
        endm

        include "extended/constantsx.asm"
        include "extended/xadd.asm"
        include "extended/xsub.asm"
        include "extended/xmul.asm"
        include "extended/xdiv.asm"
        include "extended/xcmp.asm"
        include "extended/xneg.asm"
        include "extended/xabs.asm"
        include "extended/xsqrt.asm"
        include "extended/xln.asm"
        include "extended/xlog.asm" ;log_y(x) (делается через xln)
        include "extended/xlg.asm" ;log2(x) (делается через xln)
        include "extended/xlog10.asm" ;log10(x) (делается через xln)
        include "extended/xexp.asm" ;e^x (делается через xpow2)
        include "extended/xpow.asm" ;x^y (делается через xpow2)
        include "extended/xpow10.asm" ;10^x (делается через xpow2)
        include "extended/xsin.asm"
        include "extended/xcos.asm"
        include "extended/xtan.asm"
        include "extended/xasin.asm"
        include "extended/xacos.asm"
        include "extended/xatan.asm"
        include "extended/xsinh.asm"
        include "extended/xcosh.asm"
        include "extended/xtanh.asm"
        include "extended/xasinh.asm"
        include "extended/xacosh.asm"
        include "extended/xatanh.asm"
        include "extended/xrand.asm"
        include "extended/xtostr.asm"
        include "extended/strtox.asm"

wordbuf
        ds MAXCMDSZ+1
oldcmd
        ds MAXCMDSZ+1

xnum1
        ds 10
xnum2
        ds 10
;xnum3
;        ds 10

xnumstack
;продолжается дальше вперёд

cmd_end

        ;display "cmd size ",/d,cmd_end-cmd_begin," bytes"

        savebin "calc.com",cmd_begin,cmd_end-cmd_begin
       
        LABELSLIST "..\..\us\user.l",1