home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / misc / mouse.lbr / MOUSE.MZC / MOUSE.MAC
Encoding:
Text File  |  1988-07-12  |  37.9 KB  |  1,033 lines

  1. ;
  2. ; MOUSE.MAC, Peter Grogono
  3. ;
  4. ; Update log:  Lee R. Bradley
  5. ;
  6. ;   Made M80 compatible.  Many small changes made to original program,
  7. ;   mostly cosmetic in nature.  Programs of about 16K and which may
  8. ;   use about 250 values on the calculation stack may be interpreted
  9. ;   with this version.
  10. ;
  11.            .Z80             ;Use Zilog mnemonics
  12. ;
  13. CpEnt      EQU       5H                 ;Use CP/M function
  14. Fcb        EQU       5CH                ;Default file control block
  15. Fcbex       EQU         Fcb+12        ;File extent
  16. CurRec     EQU       Fcb+32             ;Current record number
  17. Buffer       EQU         80H        ;Default file buffer
  18. Tpa        EQU       100H               ;Transient program area
  19. ;
  20. ; CP/M Entry points
  21. ;
  22. ConIn      EQU       1                  ;Read from console
  23. ConOut     EQU       2                  ;Write to console
  24. Status     EQU       11                 ;Get console status
  25. Open       EQU       15                 ;Open file
  26. Read       EQU       20                 ;Read file
  27. ;
  28. ; Program constants
  29. ;
  30. RecSize    EQU       128                ;CP/M file buffer size
  31. LocSize    EQU       26                 ;Number of local variables
  32. FrSize     EQU       5                  ;Size of environment stack frame
  33. MacSize    EQU       2*LocSize          ;Macro address table size
  34. ProgSiz    EQU       16*1024            ;Maximum size of Mouse program
  35. MaxLev     EQU       50                 ;Maximum nesting level
  36. EnvSize    EQU       FrSize*MaxLev      ;Size of environment stack
  37. StkSize    EQU       500                ;Size of local and calculation stacks
  38. ;
  39. ; Other useful constants
  40. ;
  41. Cr         EQU       13                 ;Carriage return
  42. Lf         EQU       10                 ;Line feed
  43. CtrlC      EQU       3                  ;^C to exit from trace mode
  44. Graphic    EQU       32                 ;First ASCII graphic character
  45. Width      EQU       80                 ;Width of screen
  46. Eof        EQU       1AH                ;CP/M end of file code
  47. Other      EQU       0                  ;Tag values for
  48. Macrox     EQU       1                  ; environment
  49. Param      EQU       2
  50. ;
  51. ; Macro definitions
  52. ;
  53. cpm        MACRO    func          ;Invoke a CP/M function
  54.             LD       C,func
  55.             CALL     CpEnt
  56.            ENDM
  57. ;
  58. Display    MACRO    string        ;Display a string on the console
  59.             LD       HL,string
  60.             CALL     Disp
  61.            ENDM
  62. ;
  63. skip       MACRO     lch,rch      ;Skip bracketing characters
  64.             LD       B,lch
  65.             LD       C,rch
  66.             CALL     SkipNst
  67.            ENDM
  68. ;
  69. ; Start of program
  70. ;
  71.            ASEG                ;Absolute segment
  72.            ORG       Tpa        ;Load at Tpa
  73.            LD         HL,0        ;Save Ccp's stack pointer
  74.        ADD         HL,SP
  75.        LD         (Ccp),HL
  76.            LD        SP,Stack           ;Initialize local stack
  77. nop1:      CALL      Loader             ;Load the Mouse program
  78.        LD         HL,nop1         ;In case user wants to 
  79.        LD         (HL),0        ;SAVE "compiled" program
  80.        INC         HL  
  81.            LD         (HL),0
  82.        INC         HL  
  83.            LD         (HL),0
  84. ;
  85. ; Initialize the interpreter
  86. ;
  87. init:      LD        HL,Prog
  88.            LD        (CharPos),HL
  89.            LD        IX,CalStak         ;Calculation stack pointer
  90.            LD        IY,EnvStak         ;Environment stack pointer
  91.            LD        HL,0
  92.            LD        (OffSet),HL        ;Variable address offset
  93.            LD        HL,LocSize
  94.            LD        (NxtFree),HL       ;Next free variable address
  95.            LD        A,0
  96.            LD        (Tracing),A        ;Turn off tracing
  97. ;
  98. ; Central interpreter loop
  99. ;
  100. cycle:     cpm       Status             ;Check keyboard
  101.            CP        0
  102.            JR        Z,get1             ;Jump if nothing entered
  103.            cpm       ConIn              ;Read the character entered
  104.            CP        CtrlC
  105.            JP        Z,Return           ;Return to CP/M if ^C
  106. get1:      CALL      GetChar
  107.            CP        ' '
  108.            JR        Z,get2             ;Don't trace blanks
  109.            LD        A,(Tracing)
  110.            OR        A
  111.            JR        Z,get2             ;Process character unless tracing
  112.            CALL      Trace              ;Display current environment
  113.            cpm       ConIn              ;Read a character from keyboard
  114.            OR        A                  ;Clear flags
  115.            CP        ' '
  116.            JR        Z,get2
  117.            CP        Cr
  118.            JR        Z,get2
  119.            XOR       A                  ;Turn off tracing if character
  120.            LD        (Tracing),A        ;is not a blank or a CR
  121. get2:      LD        HL,(CharPos)
  122.            LD        A,(HL)             ;Fetch the character again
  123.            CP        Graphic
  124.            JP        M,illegal          ;Reject nongraphic characters
  125.            RLCA
  126.            LD        H,0
  127.            LD        L,A                ;HL  := 2*next character
  128.            RRCA                         ;Restore character
  129.            LD        DE,-2*Graphic+CharTab
  130.            ADD       HL,DE              ;Computer table address
  131.            LD        E,(HL)
  132.            INC       HL
  133.            LD        D,(HL)
  134.            EX        DE,HL              ;HL := processing address
  135.            JP        (HL)               ;Jump to process character
  136. ;
  137. ; Jump Address table for each ASCII Graphic character
  138. ;
  139. CharTab:   DW        cycle              ;Blank
  140.            DW        exclam             ;!
  141.            DW        quote              ;"
  142.            DW        sharp              ;#
  143.            DW        Return             ;$
  144.            DW        percent            ;%
  145.            DW        file               ;&     5/19/86
  146.            DW        apost              ;'
  147.            DW        lparen             ;(
  148.            DW        rparen             ;)
  149.            DW        mul                ;*
  150.            DW        add                ;+
  151.            DW        endpar             ;,
  152.            DW        sub                ;-
  153.            DW        dot                ;.
  154.            DW        div                ;/
  155.            DW        digit              ;0
  156.            DW        digit              ;1
  157.            DW        digit              ;2
  158.            DW        digit              ;3
  159.            DW        digit              ;4
  160.            DW        digit              ;5
  161.            DW        digit              ;6
  162.            DW        digit              ;7
  163.            DW        digit              ;8
  164.            DW        digit              ;9
  165.            DW        colon              ;:
  166.            DW        endpar             ;;
  167.            DW        less               ;<
  168.            DW        equal              ;=
  169.            DW        greater            ;>
  170.            DW        query              ;?
  171.            DW        at                 ;@
  172.            DW        uc                 ;A
  173.            DW        uc                 ;B
  174.            DW        uc                 ;C
  175.            DW        uc                 ;D
  176.            DW        uc                 ;E
  177.            DW        uc                 ;F
  178.            DW        uc                 ;G
  179.            DW        uc                 ;H
  180.            DW        uc                 ;I
  181.            DW        uc                 ;J
  182.            DW        uc                 ;K
  183.            DW        uc                 ;L
  184.            DW        uc                 ;M
  185.            DW        uc                 ;N
  186.            DW        uc                 ;O
  187.            DW        uc                 ;P
  188.            DW        uc                 ;Q
  189.            DW        uc                 ;R
  190.            DW        uc                 ;S
  191.            DW        uc                 ;T
  192.            DW        uc                 ;U
  193.            DW        uc                 ;V
  194.            DW        uc                 ;W
  195.            DW        uc                 ;X
  196.            DW        uc                 ;Y
  197.            DW        uc                 ;Z
  198.            DW        lbrack             ;[
  199.            DW        mod                ;\
  200.            DW        cycle              ;]
  201.            DW        hat                ;^
  202.            DW        illegal
  203.            DW        illegal
  204.            DW        lc                 ;a
  205.            DW        lc                 ;b
  206.            DW        lc                 ;c
  207.            DW        lc                 ;d
  208.            DW        lc                 ;e
  209.            DW        lc                 ;f
  210.            DW        lc                 ;g
  211.            DW        lc                 ;h
  212.            DW        lc                 ;i
  213.            DW        lc                 ;j
  214.            DW        lc                 ;k
  215.            DW        lc                 ;l
  216.            DW        lc                 ;m
  217.            DW        lc                 ;n
  218.            DW        lc                 ;o
  219.            DW        lc                 ;p
  220.            DW        lc                 ;q
  221.            DW        lc                 ;r
  222.            DW        lc                 ;s
  223.            DW        lc                 ;t
  224.            DW        lc                 ;u
  225.            DW        lc                 ;v
  226.            DW        lc                 ;w
  227.            DW        lc                 ;x
  228.            DW        lc                 ;y
  229.            DW        lc                 ;z
  230.            DW        lbrace             ;{
  231.            DW        illegal            ;|
  232.            DW        rbrace             ;}
  233.            DW        illegal            ;~
  234.            DW        illegal            ;DEL
  235. ;
  236. ; Actions according to character class
  237. ; A = current character
  238. ;
  239. illegal:   Display   IllChar            ;Illegal character
  240.            JP        Return
  241. digit:     LD        HL,0               ;Digit
  242. dig1:      SBC       A,'0'              ;Convert to binary
  243.            JP        M,dig2             ;<0: not a digit
  244.            CP        9+1
  245.            JP        P,dig2             ;>9: not a digit
  246.            LD        D,0
  247.            LD        E,A                ;DE := digit
  248.            PUSH      DE
  249.            LD        DE,10
  250.            CALL      Multply            ;HL := 10 * temp
  251.            POP       DE
  252.            ADD       HL,DE              ;HL := 10 * temp + digit
  253.            EX        DE,HL              ;Save value in DE
  254.            CALL      GetChar
  255.            EX        DE,HL              ;Restore value
  256.            JR        dig1
  257. dig2:      CALL      PushCal
  258.            CALL      BkSpace            ;Reposition character pointer
  259.            JP        cycle
  260. add:       CALL      PopCal             ;+
  261.            EX        DE,HL              ;Pop two operands
  262.            CALL      PopCal             ;and push their sum
  263.            ADD       HL,DE
  264.            CALL      PushCal
  265.            JP        cycle
  266. sub:       CALL      Diff               ;-
  267.            CALL      PushCal            ;Pop two operands
  268.            JP        cycle              ;and push their difference
  269. mul:       CALL      PopCal             ;*
  270.            EX        DE,HL              ;Pop two operands
  271.            CALL      PopCal             ;and push their product
  272.            CALL      Multply
  273.            CALL      PushCal
  274.            JP        cycle
  275. div:       CALL      PopCal             ;/
  276.            EX        DE,HL              ;Pop two operands
  277.            CALL      PopCal             ;and push their quotient
  278.            CALL      Divide
  279.            CALL      PushCal
  280.            JP        cycle
  281. mod:       CALL      PopCal             ;\
  282.            EX        DE,HL              ;Pop two operands
  283.            CALL      PopCal             ;and push their modulus
  284.            CALL      Modulus
  285.            CALL      PushCal
  286.            JP        cycle
  287. query:     CALL      GetChar            ;?
  288.            CP        27H                ;Read from keyboard
  289.            JR        NZ,qy2
  290.            cpm       ConIn              ;Read ASCII character
  291.            LD        H,0
  292.            LD        L,A
  293.            CALL      PushCal            ;Stack it
  294.            JP        cycle
  295. qy2:       CALL      ReadNum            ;Otherwise read a number
  296.            CALL      PushCal
  297.            CALL      BkSpace            ;Reposition character pointer
  298.            JP        cycle
  299. exclam:    CALL      GetChar            ;!
  300.            CP        27H                ;Display value
  301.            JR        NZ,ex2
  302.            CALL      PopCal             ;!' displays ASCII character
  303.            LD        E,L
  304.            cpm       ConOut
  305.            JP        cycle
  306. ex2:       CALL      PopCal             ;! displays numerical value
  307.            CALL      DisNum
  308.            CALL      BkSpace            ;Reposition character pointer
  309.            JP        cycle
  310. quote:     CALL      GetChar            ;Display string
  311.            CP        '"'
  312.            JP        Z,cycle            ;Terminate at matching quote
  313.            CP        '!'
  314.            JR        Z,newline          ;! becomes CR/LF
  315.            LD        E,A
  316.            cpm       ConOut             ;Display other characters
  317.            JP        quote
  318. newline:   Display   CrLf
  319.            JP        quote
  320. uc:        SBC       A,'A'              ;Upper case letter (Global)
  321.            LD        D,0
  322.            LD        E,A                ;DE := letter (0..25)
  323.            LD        HL,0
  324.            ADD       HL,DE              ;HL := address of variable
  325.            CALL      PushCal
  326.            JP        cycle
  327. lc:        SBC       A,'a'              ;Lower case letter (Local)
  328.            LD        D,0
  329.            LD        E,A                ;DE := letter (0..25)
  330.            LD        HL,(OffSet)
  331.            ADD       HL,DE              ;HL := address of variable
  332.            CALL      PushCal
  333.            JP        cycle
  334. colon:     CALL      Addr               ;Assignment
  335.            EX        DE,HL              ;DE := address
  336.            CALL      PopCal
  337.            EX        DE,HL              ;DE := data, HL := address
  338.            LD        (HL),D
  339.            INC       HL
  340.            LD        (HL),E             ;Store value
  341.            JP        cycle
  342. dot:       CALL      Addr               ;.
  343.            LD        D,(HL)             ;Dereference
  344.            INC       HL
  345.            LD        E,(HL)             ;DE := contents
  346.            EX        DE,HL
  347.            CALL      PushCal            ;Stack contents
  348.            JP        cycle
  349. less:      CALL      Diff              ;<
  350.            JP        M,true
  351. false:     LD        HL,0              ;False = 0
  352.            CALL      PushCal
  353.            JP        cycle
  354. true:      LD        HL,1              ;True = 1
  355.            CALL      PushCal
  356.            JP        cycle
  357. equal:     CALL      Diff              ;=
  358.            JR        Z,true
  359.            JR        false
  360. greater:   CALL      Diff              ;>
  361.            CALL      Negate
  362.            LD        A,H
  363.            OR        A                 ;Set flags
  364.            JP        M,true
  365.            JR        false
  366. lbrack:    CALL      PopCal            ;[ - Skip if stack <=0
  367.            LD        A,H
  368.            OR        A
  369.            JP        M,lbr1            ;Skip if < 0
  370.            OR        L
  371.            JP        NZ,cycle          ;Skip if = 0
  372. lbr1:      skip      '[',']'
  373.            JP        cycle
  374. lparen:    LD        A,Other           ;(
  375.            CALL      PushEnv           ;Stack current position
  376.            JP        cycle
  377. rparen:    LD        H,(IY+3)          ;)
  378.            LD        L,(IY+2)          ;Restore position without
  379.            LD        (CharPos),HL      ;popping stack
  380.            JP        cycle
  381. hat:       CALL      PopCal            ;^
  382.            LD        A,H
  383.            OR        A
  384.            JP        M,hat1            ;Exit loop if < 0
  385.            OR        L
  386.            JP        NZ,cycle
  387. hat1:      CALL      PopEnv
  388.            skip      '(',')'
  389.            JP        cycle
  390. sharp:     CALL      GetChar            ;#
  391.            CP        'a'                ;Macro call
  392.            JP        M,sh1
  393.            ADD       A,'A'-'a'          ;Convert to upper case
  394. sh1:       OR        A
  395.            SBC       A,'A'              ;A..Z -> 0..25
  396.            RLCA                         ;*2 for word address
  397.            LD        B,0
  398.            LD        C,A                ;BC := offset of name
  399.            LD        A,Macrox
  400.            CALL      PushEnv            ;Save current state
  401.            LD        HL,MacDefs
  402.            ADD       HL,BC              ;HL := Address of definition
  403.            LD        E,(HL)
  404.            INC       HL
  405.            LD        D,(HL)             ;DE := macro address
  406.            LD        A,D
  407.            OR        E
  408.            JR        Z,sh2              ;Undefined macro
  409.            LD        (CharPos),DE
  410.            LD        HL,(NxtFree)
  411.            LD        (OffSet),HL
  412.            LD        DE,LocSize
  413.            ADD       HL,DE
  414.            LD        (NxtFree),HL       ;NxtFree := NxtFree + 26
  415.            JP        cycle
  416. at:        LD        HL,(NxtFree)       ;@ (Return from macro)
  417.            LD        DE,LocSize
  418.            SBC       HL,DE
  419.            LD        (NxtFree),HL       ;NxtFree := NxtFree - 26
  420. sh2:       CALL      PopEnv             ;Recover status
  421.            skip      '#',';'            ;and skip over call
  422.            JP        cycle
  423. percent:   LD        A,Param            ;% - formal parameter
  424.            CALL      PushEnv            ;Save current state
  425.            LD        C,1                ;parbal := 1
  426.            PUSH      IY                 ;Save environment stack pointer
  427. pc1:       LD        DE,5
  428.            ADD       IY,DE              ;Next stack frame
  429.            LD        A,(IY+1)           ;Get tag value
  430.            CP        Macrox
  431.            JR        NZ,pc2             ;tag = macro
  432.            DEC       C                  ;parbal := parbal - 1
  433.            JR        pc3
  434. pc2:       CP        Param
  435.            JR        NZ,pc3             ;tag = param
  436.            INC       C                  ;parbal := parbal + 1
  437. pc3:       LD        A,C
  438.            OR        A
  439.            JR        NZ,pc1             ;Loop until match
  440. pc4:       LD        H,(IY+5)
  441.            LD        L,(IY+4)
  442.            LD        (OffSet),HL        ;Recover offset
  443.            LD        H,(IY+3)           ; for calling environment
  444.            LD        L,(IY+2)
  445.            LD        (CharPos),HL       ;Restore position of call
  446.            POP       IY                 ;Restore frame stack pointer
  447.            CALL      PopCal
  448.            LD        E,L                ;E := parnum
  449. pc5:       CALL      GetChar            ;Search for actual parameter
  450.            CP        '"'
  451.            JR        NZ,pc6
  452.            CALL      SkipStr
  453.            JR        pc5
  454. pc6:       CP        '#'
  455.            JR        NZ,pc7
  456.            skip      '#',';'
  457.            JR        pc5
  458. pc7:       CP        ','
  459.            JR        NZ,pc8
  460.            DEC       E                  ;parnum := parnum -1
  461.            JR        pc9
  462. pc8:       CP        ';'
  463.            JR        NZ,pc9
  464.            CALL      PopEnv             ;Null parameter
  465.            JP        cycle
  466. pc9:       LD        A,E
  467.            OR        A
  468.            JR        NZ,pc5             ;Loop until parameter found
  469.            JP        cycle
  470. endpar:    CALL      PopEnv             ;, or ;
  471.            JP        cycle
  472. apost:     CALL      GetChar            ;'
  473.            LD        H,0                ;Push ASCII character onto
  474.            LD        L,A                ; stack
  475.            CALL      PushCal
  476.            JP        cycle
  477. lbrace:    LD        A,1                ;{
  478.            LD        (Tracing),A        ;Turn on tracing
  479.            JP        cycle
  480. rbrace:    XOR       A                  ;}
  481.            LD        (Tracing),A        ;Turn off tracing
  482.            JP        cycle
  483. file:        LD         DE,Fcbex        ;&
  484.        XOR         A            ;Load .MSE file
  485.        LD         (DE),A        ;Clear key bytes in Fcb
  486.        INC         DE
  487.        LD         (DE),A
  488.        INC         DE
  489.        LD         (DE),A
  490.        INC         DE
  491.        LD         (DE),A
  492.            LD         DE,CurRec    
  493.        LD         (DE),A
  494.        LD         C,9        ;Keep track of number of 
  495.        LD         DE,Fcb        ;characters in filename
  496.        LD         (DE),A
  497. f1:        CALL      GetChar        ;Put characters in Fcb
  498.        CP         '&'        ;until delimiting & found
  499.        JR         Z,f2
  500.        INC         DE
  501.        DEC       C
  502.            LD         (DE),A
  503.            JR         f1
  504. f2:        LD         A,' '        ;Pad if necessary with blanks 
  505. f3:        DEC         C
  506.        JR         Z,f4
  507.        INC         DE
  508.        LD         (DE),A
  509.        JR         f3
  510. f4:       INC         DE            ;Tack on MSE extension
  511.        LD         A,'M'
  512.            LD         (DE),A
  513.        INC         DE
  514.        LD         A,'S'
  515.        LD         (DE),A
  516.        INC         DE
  517.        LD         A,'E'
  518.        LD         (DE),A
  519.        CALL         Loader        ;Load it and then jump
  520.        JP         init           ;to initialization code
  521. ;
  522. ; Subroutines
  523. ;
  524. ; The Mouse program loader
  525. ;
  526. Loader:    Display   Signon
  527.            LD        DE,Fcb             ;Open the input file
  528.            cpm       Open
  529.            CP        255
  530.            JP        NZ,readfil
  531.            Display   OpnFail            ;File could not be opened
  532.            JP        Return
  533. readfil:   Display   Reading
  534.            LD        B,MacSize          ;Clear macro table
  535.            LD        HL,MacDefs
  536. clemac:    LD        (HL),0
  537.            INC       HL
  538.            DJNZ      clemac
  539.            LD        BC,ProgSiz          ;Clear program area
  540.            LD        HL,Prog
  541. clepgm:    LD        (HL),0
  542.            INC       HL
  543.            DEC       BC
  544.            LD        A,B
  545.            OR        C
  546.            JR        NZ,clepgm
  547.            LD        IX,Buffer+RecSize
  548.            LD        IY,Prog            ;Set input and output pointers
  549. ld1:       CALL      Gch
  550. ld2:       CP        ' '
  551.            JP        P,ld3
  552.            LD        A,' '
  553.            CALL      Store              ;Convert nongraphic characters
  554.            JR        ld1                ;to blanks
  555. ld3:       JR        NZ,ld5
  556.            CALL      Store              ;Store first blank
  557. ld4:       CALL      Gch
  558.            CP        ' '
  559.            JR        Z,ld4              ;Ignore following blanks
  560.            JR        ld2
  561. ld5:       CP        '~'
  562.            JR        NZ,ld7
  563. ld6:       CALL      Gch                ;Remove comments by
  564.            CP        Cr                 ;skipping to EOL
  565.            JR        NZ,ld6
  566.            JR        ld1
  567. ld7:       CP        '"'
  568.            JR        NZ,ld9
  569.            CALL      Store              ;Store strings as is
  570. ld8:       CALL      Gch
  571.            CALL      Store
  572.            LD        A,(IY)             ;Retrieve character
  573.            CP        '"'
  574.            JR        NZ,ld8
  575.            JR        ld1
  576. ld9:       CP        '$'
  577.        JR        NZ,ld11
  578.            LD         A,(IY)
  579.        CP         ''''
  580.        LD         A,'$'
  581.        JR         NZ,ld91
  582.           JP         ld11
  583. ld91:      CALL      Store              ;Store $ as terminator
  584.            CALL      Gch                ;Macro definition
  585.          CP         '@'        ;Test for program without
  586.        JP         P,ld9a        ;any Macros (05/03/86)
  587.        JR        ld1                ;If not, loop.
  588. ld9a:      CP        'a'
  589.            JP        M,ld10
  590.            ADD       A,'A'-'a'          ;Convert lower to upper case
  591. ld10:      OR        A
  592.            SBC       A,'A'              ;A..Z -> 0..25
  593.            RLCA                         ;* 2 for word address
  594.            LD        D,0
  595.            LD        E,A
  596.            LD        HL,MacDefs         ;Address of definitions
  597.            ADD       HL,DE              ;HL -> definition pointer
  598.            PUSH      IY
  599.            POP       DE                 ;DE := IY
  600.            LD        (HL),E
  601.            INC       HL
  602.            LD        (HL),D             ;Store pointer to definition
  603.            JR        ld1
  604. ld11:      CALL      Store              ;Store everything else
  605.            JR        ld1
  606. ;
  607. ; Put next character from file Buffer into A register.
  608. ; A new Buffer is read when IX = Buffer + 128.
  609. ;
  610. Gch:       PUSH      IX
  611.            POP       HL                 ;HL := IX
  612.            LD        DE,Buffer+RecSize
  613.            OR        A
  614.            SBC       HL,DE              ;HL := IX - buffer - 128
  615.            JR        NZ,Gch1
  616.            LD        DE,Fcb             ;Read next sector
  617.            cpm       Read
  618.            OR        A
  619.            JR        NZ,Gch2            ;Jump if end of file
  620.            LD        E,'.'
  621. ;          cpm       ConOut             ;Show progress
  622.            LD        IX,Buffer          ;Reset pointer
  623. Gch1:      LD        A,(IX)             ;Get character
  624.            OR        A                  ;Clear carry
  625.            CP        Eof
  626.            JR        Z,Gch2
  627.            OR        A
  628.            INC       IX
  629.            RET
  630. Gch2:      Display   Loaded             ;End of file
  631.            POP       HL                 ;Pop link to Gch
  632.            RET                          ;Return from Loader
  633. ;
  634. ; Store character in A register in Program Buffer.
  635. ;
  636. Store:     INC       IY
  637.            LD        (IY),A
  638.            PUSH      IY
  639.            POP       HL                 ;HL := IY
  640.            LD        DE,ProgTop
  641.            OR        A
  642.            SBC       HL,DE              ;Return if there is
  643.            RET       M                  ;space for more program
  644.            Display   TooLong
  645.            JP        Return
  646. ;
  647. ; Get next character from Program Buffer.
  648. ; On exit: A contains character;
  649. ; HL points to character in Buffer.
  650. ;
  651. GetChar:   LD       HL,(CharPos)
  652.            INC      HL
  653.            LD       (CharPos),HL
  654.            LD       A,(HL)
  655.            OR       A                   ;Clear carry
  656.            RET
  657. ;
  658. ; Backspace the character pointer
  659. ;
  660. BkSpace:   LD        HL,(CharPos)
  661.            DEC       HL
  662.            LD        (CharPos),HL
  663.            RET
  664. ;
  665. ; Calculation Stack.
  666. ; IX is the calculation Stack Pointer.
  667. ; HL is pushed/popped from the Stack.
  668. ; Underflow/overflow is not checked.
  669. ; The Stack looks like this between calls:
  670. ;
  671. ;          IX  ->        |   |
  672. ;          IX+1          |LSB|
  673. ;          IX+2          |MSB|
  674. ;
  675. PushCal:   LD        (IX),H
  676.            DEC       IX
  677.            LD        (IX),L
  678.            DEC       IX
  679.            RET
  680. PopCal:    INC       IX
  681.            LD        L,(IX)
  682.            INC       IX
  683.            LD        H,(IX)
  684.            RET
  685. ;
  686. ; Frame Stack.
  687. ; Each entry has 5 bytes.  IY is the Stack pointer.
  688. ; Overflow/underflow is not checked.  Destroys DE.
  689. ; On entry, A is assumed to hold the tag value.
  690. ; Between calls the Stack looks like this:
  691. ;
  692. ;          IY ->     |             |
  693. ;          IY+1      | tag         |
  694. ;          IY+2      | LSB CharPos |
  695. ;          IY+3      | MSB CharPos |
  696. ;          IY+4      | LSB OffSet  |
  697. ;          IY+5      | MSB OffSet  |
  698. ;
  699. PushEnv:   LD        DE,-5
  700.            ADD       IY,DE
  701.            LD        (IY+1),A
  702.            LD        HL,(CharPos)
  703.            LD        (IY+2),L
  704.            LD        (IY+3),H
  705.            LD        HL,(OffSet)
  706.            LD        (IY+4),L
  707.            LD        (IY+5),H
  708.            RET
  709. PopEnv:    LD        H,(IY+5)
  710.            LD        L,(IY+4)
  711.            LD        (OffSet),HL
  712.            LD        H,(IY+3)
  713.            LD        L,(IY+2)
  714.            LD        (CharPos),HL
  715.            LD        DE,5
  716.            ADD       IY,DE
  717.            RET
  718. ;
  719. ; Skip over a string. On entry the character " has
  720. ; been seen.  This subroutine looks for the next ".
  721. ; Destroys A, HL
  722. ;
  723. SkipStr:   CALL      GetChar
  724.            CP        '"'
  725.            JP        NZ,SkipStr
  726.            RET
  727. ;
  728. ; Skip bracketing characters.
  729. ; On entry B = left character(e.g. [)
  730. ; and C = right character (e.g. ])
  731. ; Destroys A, D, HL; must preserve E for % processing.
  732. ;
  733. SkipNst:   LD        D,1                ;Level counter
  734. sk1:       XOR       A                  ;A := 0
  735.            CP        D
  736.            RET       Z                  ;Return when level counter = 0
  737. sk2:       CALL      GetChar
  738.            CP        '"'
  739.            JR        NZ,sk3
  740.            CALL      SkipStr            ;Skip a string
  741.            JR        sk2
  742. sk3:       CP        B
  743.            JR        NZ,sk4
  744.            INC       D                  ;Left character
  745.            JR        sk1
  746. sk4:       CP        C
  747.            JR        NZ,sk1
  748.            DEC       D                  ;Right character
  749.            JR        sk1
  750. ;
  751. ; Display HL as a signed decimal string followed by a blank.
  752. ; All registers destroyed.
  753. ;
  754. DisNum:    LD        A,H
  755.            OR        A
  756.            JP        P,ds1
  757.            CALL      Negate             ;Number is negative
  758.            PUSH      HL                 ;Save its value
  759.            LD        E,'-'
  760.            cpm       ConOut
  761.            POP       HL                 ;Restore number
  762. ds1:       LD        D,1
  763.            PUSH      DE                 ;Set last digit flag
  764. ds2:       LD        DE,10
  765.            CALL      divmod             ;BC := HL/10, HL := HL\10
  766.            PUSH      HL
  767.            LD        H,B                ;Restore quotient
  768.            LD        L,C
  769.            LD        A,H
  770.            OR        L
  771.            JR        NZ,ds2             ;Loop until quotient is zero
  772. ds3:       POP       DE                 ;Restore digit
  773.            LD        A,D
  774.            OR        A
  775.            RET       NZ                 ;Exit when flag is found
  776.            LD        A,E
  777.            ADD       A,'0'              ;Convert digit to ASCII
  778.            LD        E,A
  779.            cpm       ConOut             ;Display digit
  780.            JR        ds3
  781. ;
  782. ; Read a signed number from the keyboard.
  783. ; HL := value of number; other registers destroyed
  784. ;
  785. ReadNum:   cpm       ConIn              ;Read a character
  786.            LD        HL,0               ;Initialize value register
  787.            CP        '-'
  788.            PUSH      AF                 ;Save sign flag
  789.            JR        Z,rd3              ;Read first digit
  790. rd2:       SBC       A,'0'
  791.            JP        M,rd4              ;Exit if character < '0'
  792.            CP        9+1
  793.            JP        P,rd4              ;Exit if character > '9'
  794.            LD        D,0                ;DE := digit
  795.            LD        E,A
  796.            PUSH      DE
  797.            LD        DE,10
  798.            CALL      Multply            ;Value := 10 * value
  799.            POP       DE
  800.            ADD       HL,DE              ;+ digit
  801. rd3:       PUSH      HL
  802.            cpm       ConIn              ;Read another digit
  803.            POP       HL
  804.            JP        rd2
  805. rd4:       POP       AF                 ;Restore sign flag
  806.            CALL      Z,Negate           ;Negate register if '-'
  807.            RET
  808. ;
  809. ; Set HL := second operand - first operand.
  810. ; Destroys DE
  811. ;
  812. Diff:      CALL      PopCal
  813.            EX        DE,HL
  814.            CALL      PopCal
  815.            SBC       HL,DE
  816.            RET
  817. ;
  818. ; Pop the calculation stack and convert result to an address
  819. ; in the data area.  The entry in the stack consists of a
  820. ; letter value (0..25) + the current offset.
  821. ;
  822. Addr:      CALL      PopCal
  823.            ADD       HL,HL              ;HL := 2 * (letter + offset)
  824.            LD        DE,Data
  825.            ADD       HL,DE
  826.            RET
  827. ;
  828. ; Multiply subroutine.
  829. ; HL := HL * DE; other registers destroyed.
  830. ;
  831. Multply:   LD        A,H
  832.            XOR       D
  833.            PUSH      AF
  834.            CALL      MakePos            ;Make operands positive
  835.            LD        B,H                ;BC := HL
  836.            LD        C,L
  837.            LD        HL,0               ;HL := 0 (result register)
  838. my1:       SRA       B                  ;BC := BC/2
  839.            RR        C                  ;LSB to carry
  840.            JR        NC,my2
  841.            ADD       HL,DE              ;Add multiplicand if bit set
  842. my2:       LD        A,B
  843.            OR        C
  844.            JR        Z,my3              ;Finished if BC = 0
  845.            SLA       E                  ;DE := 2 * DE
  846.            RL        D
  847.            JR        my1
  848. my3:       POP       AF
  849.            CALL      M,Negate           ;Negate result if necessary
  850.            RET
  851. ;
  852. ; Divide subroutine
  853. ; HL := HL div DE; other registers destroyed.
  854. ;
  855. Divide:    LD        A,H
  856.            XOR       D
  857.            PUSH      AF                 ;Save sign of result
  858.            CALL      divmod
  859.            LD        H,B                ;Get quotient
  860.            LD        L,C
  861.            POP       AF
  862.            CALL      M,Negate           ;Negate result if necessary
  863.            RET
  864. ;
  865. ; Modulus subroutine.
  866. ; HL := HL mod DE; other registers destroyed.
  867. ;
  868. Modulus:   LD        A,H
  869.            XOR       D
  870.            PUSH      AF                 ;Save sign of result
  871.            CALL      divmod
  872.            POP       AF
  873.            CALL      M,Negate           ;Negate result if necessary
  874.            RET
  875. ;
  876. ; This does the work for 'divide' and 'modulus'.
  877. ; BC := HL div DE; HL := HL mod DE; other registers destroyed
  878. ;
  879. divmod:    LD        A,D
  880.            OR        E
  881.            JR        Z,DivErr           ;Attempted divide by zero
  882.            CALL      MakePos            ;Make operands positive
  883.            XOR       A                  ;A := 0
  884. dm1:       EX        DE,HL
  885. dm2:       BIT       6,H                ;Normalize divisor
  886.            JR        NZ,dm3
  887.            INC       A
  888.            ADD       HL,HL              ;Shift left
  889.            JR        dm2
  890. dm3:       EX        DE,HL
  891.            LD        BC,0               ;BC := 0 (result register)
  892.            INC       A
  893. dm4:       OR        A                  ;Clear flags
  894.            SBC       HL,DE              ;Subtract divisor
  895.            CCF
  896.            JR        C,dm5
  897.            ADD       HL,DE              ;Result is negative
  898.            OR        A
  899. dm5:       RL        C                  ;Shift 0 or 1 into quotient
  900.            RL        B
  901.            SRA       D                  ;Shift divisor
  902.            RR        E
  903.            DEC       A                  ;Count bits
  904.            JR        NZ,dm4
  905.            RET
  906.  
  907. ;
  908. ; Make HL and DE positive
  909. ;
  910. MakePos:   BIT       7,H
  911.            JR        Z,sg1
  912.            CALL      Negate             ;Make HL positive
  913. sg1:       BIT       7,D
  914.            RET       Z
  915.            EX        DE,HL
  916.            CALL      Negate             ;Make DE positive
  917.            EX        DE,HL
  918.            RET
  919. ;
  920. ; Negate HL.
  921. ;
  922. Negate:    LD        A,H                ;Complement H
  923.            CPL
  924.            LD        H,A
  925.            LD        A,L                ;Complement L
  926.            CPL
  927.            LD        L,A
  928.            INC       HL                 ;Increment for 1's complement
  929.            RET
  930.  
  931. DivErr:    Display   DivZero
  932.            CALL      Trace
  933.            JP        Return
  934. ;
  935. ; Display current environment: output 40 characters
  936. ; before and after current character position
  937. ; and show current position.
  938. ; Destroys all registers.
  939. ;
  940. Trace:     Display   CrLf
  941.            LD        HL,(CharPos)
  942.            LD        DE,Width/2         ;Half screen width
  943.            SBC       HL,DE              ;HL := character position - 40
  944.            LD        B,Width            ;# of characters to be displayed
  945. tr1:       LD        A,(HL)             ;Get a character
  946.            PUSH      HL
  947.            LD        DE,Prog
  948.            SBC       HL,DE
  949.            JP        M,tr2              ;Convert character to blank
  950.            LD        HL,ProgTop-1       ;if it is outside the program buffer
  951.            POP       DE
  952.            PUSH      DE
  953.            SBC       HL,DE              ;or not an ASCII graphic character
  954.            JP        M,tr2
  955.            CP        Graphic
  956.            JP        P,tr3
  957. tr2:       LD        A,' '
  958. tr3:       LD        E,A
  959.            PUSH      BC
  960.            cpm       ConOut             ;Display the character
  961.            POP       BC
  962.            POP       HL
  963.            INC       HL
  964.            DJNZ      tr1                ;Display 80 characters
  965.            Display   CrLf
  966.            LD        B,Width/2
  967. tr4:       LD        E,' '
  968.            PUSH      BC
  969.            cpm       ConOut             ;Display 40 blanks
  970.            POP       BC
  971.            DJNZ      tr4
  972.            LD        E,'^'
  973.            cpm       ConOut             ;Point to offending character
  974.            Display   CrLf
  975.            RET
  976. ;
  977. ;
  978. ; Display a message.  HL is the address of a string of bytes
  979. ; terminated by a zero byte.  Destroys all registers.
  980. ;
  981. Disp:      LD       A,(HL)              ;Get a character from message
  982.            OR       A
  983.            RET      Z                   ;Finished if zero
  984.            INC      HL
  985.            PUSH     HL                  ;Save pointer
  986.            LD       E,A
  987.            cpm      ConOut              ;Display the character
  988.            POP      HL
  989.            JP       Disp
  990. ;
  991. ; Return to operating system
  992. ;
  993. Return:    Display   CrLf
  994.            Display   Signoff
  995.        LD         HL,(Ccp)        ;Quiet return (05/03/86)
  996.            LD         SP,HL
  997.        RET
  998.  
  999. ;
  1000. ; Messages
  1001. ;
  1002. CrLf:      DB        Cr,Lf,0
  1003. IllChar:   DB        Cr,Lf,'Illegal character',0
  1004. TooLong:   DB        ' Program is too long for buffer.',0
  1005. OpnFail:   DB          'File not found',Cr,Lf,0
  1006. Loaded:    DB        0
  1007. Reading:   DB        0
  1008. DivZero:   DB        Cr,Lf,'Division/modulus by zero',0
  1009. ;
  1010. ; Data
  1011. ;
  1012. Ccp:       DW         0            ;Ccp address; used for quiet return
  1013. CharPos:   DW        0                  ;Current character pointer
  1014. OffSet:    DW        0                  ;Current variable address offset
  1015. NxtFree:   DW        0                  ;Next free address for local data
  1016. Tracing:   DB        0                  ;0 = no tracing, 1 = tracing
  1017. Signon:    DB        'MOUSE.MAC, 6/15/86',Cr,Lf,0
  1018. Signoff:   DB        0
  1019. MacDefs:   DB        0                  ;Macro definition table
  1020. Prog       EQU       MacDefs+MacSize    ;Start of Mouse program
  1021. ProgTop    EQU       Prog+ProgSiz       ;End of Mouse program
  1022. Stack      EQU       ProgTop+StkSize    ;Top of local stack
  1023. CalcLim    EQU       Stack+1            ;Limit of calculation stack
  1024. CalStak    EQU       CalcLim+StkSize    ;Top of calculation stack
  1025. EnvLim     EQU       CalStak+1          ;Limit of environment stack
  1026. EnvStak    EQU       EnvLim+EnvSize     ;Top of environment stack
  1027. Data       EQU       EnvStak+1        ;Local data area
  1028. MaxAddr    EQU       2*LocSize*MaxLev+Data
  1029.            END
  1030.  environment stack
  1031. Data       EQU       EnvStak+1        ;Local data area
  1032. MaxAddr    EQU       2*LocSize*MaxLev+Data
  1033.