home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / cpmug / cpmug011.ark / TINIDISK.ASM < prev    next >
Encoding:
Assembly Source File  |  1985-02-10  |  63.4 KB  |  1,905 lines

  1. ;**************************************************************
  2. ;* 
  3. ;*                TINY BASIC FOR INTEL 8080
  4. ;*                      VERSION 1.0
  5. ;*                    BY LI-CHEN WANG
  6. ;*                     10 JUNE, 1976 
  7. ;*                       @COPYLEFT 
  8. ;*                  ALL WRONGS RESERVED
  9. ;* 
  10. ;**************************************************************
  11. ;* 
  12. ;*  ;*** ZERO PAGE SUBROUTINES ***
  13. ;* 
  14. ;*  THE 8080 INSTRUCTION SET LETS YOU HAVE 8 ROUTINES IN LOW 
  15. ;*  MEMORY THAT MAY BE CALLED BY RST N, N BEING 0 THROUGH 7. 
  16. ;*  THIS IS A ONE BYTE INSTRUCTION AND HAS THE SAME POWER AS 
  17. ;*  THE THREE BYTE INSTRUCTION CALL LLHH.  TINY BASIC WILL 
  18. ;*  USE RST 0 AS START AND RST 1 THROUGH RST 7 FOR 
  19. ;*  THE SEVEN MOST FREQUENTLY USED SUBROUTINES.
  20. ;*  TWO OTHER SUBROUTINES (CRLF AND TSTNUM) ARE ALSO IN THIS 
  21. ;*  SECTION.  THEY CAN BE REACHED ONLY BY 3-BYTE CALLS.
  22. ;*  IN ORDER TO CONFIGURE THE SYSTEM FOR USE WITH CPM I HAVE
  23. ;*  MOVED SOME OF THE ROUTINES AROUND.  START WILL NOW BE AT
  24. ;*  LOCATION 100H AND THIS SECTION WILL END AT LOCATION 3FH
  25. ;*  WITH A JUMP TO 108H.
  26. ;* 
  27. ;       ORG  8H
  28. ;       XTHL           ;*** TSTC OR RST 1 *** 
  29. ;       RST  5         ;IGNORE BLANKS AND 
  30. ;       CMP  M         ;TEST CHARACTER
  31. ;       JMP  TC1       ;REST OF THIS IS AT TC1
  32. ;* 
  33. ;CRLF   MVI  A,0DH     ;*** CRLF ***
  34. ;* 
  35. ;       PUSH PSW       ;*** OUTC OR RST 2 *** 
  36. ;       LDA  OCSW      ;PRINT CHARACTER ONLY
  37. ;       ORA  A         ;IFF OCSW SWITCH IS ON
  38. ;       JMP  OC2       ;REST OF THIS IS AT OC2
  39. ;* 
  40. ;       CALL EXPR2     ;*** EXPR OR RST 3 *** 
  41. ;       PUSH H         ;EVALUATE AN EXPRESION 
  42. ;       JMP  EXPR1     ;REST OF IT IS AT EXPR1
  43. ;       DB   'W' 
  44. ;* 
  45. ;       MOV  A,H       ;*** COMP OR RST 4 *** 
  46. ;       CMP  D         ;COMPARE HL WITH DE
  47. ;       RNZ            ;RETURN CORRECT C AND
  48. ;       MOV  A,L       ;Z FLAGS 
  49. ;       CMP  E         ;BUT OLD A IS LOST 
  50. ;       RET
  51. ;       DB   'AN'
  52. ;* 
  53. ;SS1    LDAX D         ;*** IGNBLK/RST 5 ***
  54. ;       CPI  40Q       ;IGNORE BLANKS 
  55. ;       RNZ            ;IN TEXT (WHERE DE->)
  56. ;       INX  D         ;AND RETURN THE FIRST
  57. ;       JMP  SS1       ;NON-BLANK CHAR. IN A
  58. ;* 
  59. ;       POP  PSW       ;*** FINISH/RST 6 ***
  60. ;       CALL FIN       ;CHECK END OF COMMAND
  61. ;       JMP  QWHAT     ;PRINT "WHAT?" IFF WRONG
  62. ;       DB   'G' 
  63. ;* 
  64. ;       RST  5         ;*** TSTV OR RST 7 *** 
  65. ;       SUI  100Q      ;TEST VARIABLES
  66. ;       RC             ;C:NOT A VARIABLE
  67. ;       JMP  TSTV1     ;JUMP AROUND RESERVED AREA
  68.        ORG  100H      ;OF CPM.
  69. START  JMP  NINIT      ;GO TO INITIALIZATION ROUTINE.    JIF
  70. TSTV1  JNZ  TV1       ;NOT "@" ARRAY 
  71.        INX  D         ;IT IS THE "@" ARRAY 
  72.        CALL PARN      ;@ SHOULD BE FOLLOWED
  73.        DAD  H         ;BY (EXPR) AS ITS INDEX
  74.        JC   QHOW      ;IS INDEX TOO BIG? 
  75.        PUSH D         ;WILL IT OVERWRITE 
  76.        XCHG           ;TEXT? 
  77.        CALL SIZE      ;FIND SIZE OF FREE 
  78.        RST  4         ;AND CHECK THAT
  79.        JC   ASORRY    ;IFF SO, SAY "SORRY"
  80. SS1A   LXI  H,VARBGN  ;IFF NOT, GET ADDRESS 
  81.        CALL SUBDE     ;OF @(EXPR) AND PUT IT 
  82.        POP  D         ;IN HL 
  83.        RET            ;C FLAG IS CLEARED 
  84. TV1    CPI  33Q       ;NOT @, IS IT A TO Z?
  85.        CMC            ;IFF NOT RETURN C FLAG
  86.        RC 
  87.        INX  D         ;IFF A THROUGH Z
  88. TV1A   LXI  H,VARBGN  ;COMPUTE ADDRESS OF
  89.        RLC            ;THAT VARIABLE 
  90.        ADD  L         ;AND RETURN IT IN HL 
  91.        MOV  L,A       ;WITH C FLAG CLEARED 
  92.        MVI  A,0 
  93.        ADC  H 
  94.        MOV  H,A 
  95.        RET
  96. ;* 
  97. ;*                 TSTC   XCH  HL,(SP)   ;*** TSTC OR RST 1 *** 
  98. ;*                        IGNBLK         THIS IS AT LOC. 8 
  99. ;*                        CMP  M         AND THEN JMP HERE 
  100. TC1    INX  H         ;COMPARE THE BYTE THAT 
  101.        JZ   TC2       ;FOLLOWS THE RST INST. 
  102.        PUSH B         ;WITH THE TEXT (DE->)
  103.        MOV  C,M       ;IFF NOT =, ADD THE 2ND 
  104.        MVI  B,0       ;BYTE THAT FOLLOWS THE 
  105.        DAD  B         ;RST TO THE OLD PC 
  106.        POP  B         ;I.E., DO A RELATIVE 
  107.        DCX  D         ;JUMP IFF NOT = 
  108. TC2    INX  D         ;IFF =, SKIP THOSE BYTES
  109.        INX  H         ;AND CONTINUE
  110.        XTHL 
  111.        RET
  112. ;* 
  113. TSTNUM LXI  H,0       ;*** TSTNUM ***
  114.        MOV  B,H       ;TEST IFF THE TEXT IS 
  115.        RST  5         ;A NUMBER
  116. TN1    CPI  60Q       ;IFF NOT, RETURN 0 IN 
  117.        RC             ;B AND HL
  118.        CPI  72Q       ;IFF NUMBERS, CONVERT 
  119.        RNC            ;TO BINARY IN HL AND 
  120.        MVI  A,360Q    ;SET A TO # OF DIGITS
  121.        ANA  H         ;IFF H>255, THERE IS NO 
  122.        JNZ  QHOW      ;ROOM FOR NEXT DIGIT 
  123.        INR  B         ;B COUNTS # OF DIGITS
  124.        PUSH B 
  125.        MOV  B,H       ;HL=10;*HL+(NEW DIGIT)
  126.        MOV  C,L 
  127.        DAD  H         ;WHERE 10;* IS DONE BY
  128.        DAD  H         ;SHIFT AND ADD 
  129.        DAD  B 
  130.        DAD  H 
  131.        LDAX D         ;AND (DIGIT) IS FROM 
  132.        INX  D         ;STRIPPING THE ASCII 
  133.        ANI  17Q       ;CODE
  134.        ADD  L 
  135.        MOV  L,A 
  136.        MVI  A,0 
  137.        ADC  H 
  138.        MOV  H,A 
  139.        POP  B 
  140.        LDAX D         ;DO THIS DIGIT AFTER 
  141.        JP   TN1       ;DIGIT. S SAYS OVERFLOW
  142. QHOW   PUSH D         ;*** ERROR: "HOW?" *** 
  143. AHOW   LXI  D,HOW 
  144.        JMP  ERROR 
  145. HOW    DB   'HOW?',0DH 
  146. OK     DB   'OK',0DH 
  147. WHAT   DB   'WHAT?',0DH 
  148. SORRY  DB   'SORRY',0DH 
  149. ;* 
  150. ;**************************************************************
  151. ;* 
  152. ;* *** MAIN ***
  153. ;* 
  154. ;* THIS IS THE MAIN LOOP THAT COLLECTS THE TINY BASIC PROGRAM
  155. ;* AND STORES IT IN THE MEMORY.
  156. ;* 
  157. ;* AT START, IT PRINTS OUT "(CR)OK(CR)", AND INITIALIZES THE 
  158. ;* STACK AND SOME OTHER INTERNAL VARIABLES.  THEN IT PROMPTS 
  159. ;* ">" AND READS A LINE.  IFF THE LINE STARTS WITH A NON-ZERO 
  160. ;* NUMBER, THIS NUMBER IS THE LINE NUMBER.  THE LINE NUMBER
  161. ;* (IN 16 BIT BINARY) AND THE REST OF THE LINE (INCLUDING CR)
  162. ;* IS STORED IN THE MEMORY.  IFF A LINE WITH THE SAME LINE
  163. ;* NUMBER IS ALREDY THERE, IT IS REPLACED BY THE NEW ONE.  IF
  164. ;* THE REST OF THE LINE CONSISTS OF A 0DHONLY, IT IS NOT STORED
  165. ;* AND ANY EXISTING LINE WITH THE SAME LINE NUMBER IS DELETED. 
  166. ;* 
  167. ;* AFTER A LINE ISs INSERTED, REPLACED, OR DELETED, THE PROGRAM 
  168. ;* LOOPS BACK AND ASK FOR ANOTHER LINE.  THIS LOOP WILL BE 
  169. ;* TERMINATED WHEN IT READS A LINE WITH ZERO OR NO LINE
  170. ;* NUMBER; AND CONTROL IS TRANSFERED TO "DIRCT".
  171. ;* 
  172. ;* TINY BASIC PROGRAM SAVE AREA STARTS AT THE MEMORY LOCATION
  173. ;* LABELED "TXTBGN" AND ENDED AT "TXTEND".  WE ALWAYS FILL THIS
  174. ;* AREA STARTING AT "TXTBGN", THE UNFILLED PORTION IS POINTED
  175. ;* BY THE CONTENT OF A MEMORY LOCATION LABELED "TXTUNF". 
  176. ;* 
  177. ;* THE MEMORY LOCATION "CURRNT" POINTS TO THE LINE NUMBER
  178. ;* THAT IS CURRENTLY BEING INTERPRETED.  WHILE WE ARE IN 
  179. ;* THIS LOOP OR WHILE WE ARE INTERPRETING A DIRECT COMMAND 
  180. ;* (SEE NEXT SECTION), "CURRNT" SHOULD POINT TO A 0. 
  181. ;* 
  182. RSTART LXI  SP,STACK  ;SET STACK POINTER
  183. ST1    CALL CRLF      ;AND JUMP TO HERE
  184.        LXI  D,OK      ;DE->STRING
  185.        SUB  A         ;A=0 
  186.        CALL PRTSTG    ;PRINT STRING UNTIL 0DH
  187.        LXI  H,ST2+1   ;LITERAL 0 
  188.        SHLD CURRNT    ;CURRNT->LINE # = 0
  189. ST2    LXI  H,0 
  190.        SHLD LOPVAR
  191.        SHLD STKGOS
  192. ST3    MVI  A,76Q     ;PROMPT '>' AND
  193.        CALL GETLN     ;READ A LINE 
  194.        PUSH D         ;DE->END OF LINE 
  195. ST3A   LXI  D,BUFFER  ;DE->BEGINNING OF LINE 
  196.        CALL TSTNUM    ;TESt IFF IT IS A NUMBER
  197.        RST  5 
  198.        MOV  A,H       ;HL=VALUE OF THE # OR
  199.        ORA  L         ;0 IFF NO # WAS FOUND 
  200.        POP  B         ;BC->END OF LINE 
  201.        JZ   DIRECT
  202.        DCX  D         ;BACKUP DE AND SAVE
  203.        MOV  A,H       ;VALUE OF LINE # THERE 
  204.        STAX D 
  205.        DCX  D 
  206.        MOV  A,L 
  207.        STAX D 
  208.        PUSH B         ;BC,DE->BEGIN, END 
  209.        PUSH D 
  210.        MOV  A,C 
  211.        SUB  E 
  212.        PUSH PSW       ;A=# OF BYTES IN LINE
  213.        CALL FNDLN     ;FIND THIS LINE IN SAVE
  214.        PUSH D         ;AREA, DE->SAVE AREA 
  215.        JNZ  ST4       ;NZ:NOT FOUND, INSERT
  216.        PUSH D         ;Z:FOUND, DELETE IT
  217.        CALL FNDNXT    ;FIND NEXT LINE
  218. ;*                                       DE->NEXT LINE 
  219.        POP  B         ;BC->LINE TO BE DELETED
  220.        LHLD TXTUNF    ;HL->UNFILLED SAVE AREA
  221.        CALL MVUP      ;MOVE UP TO DELETE 
  222.        MOV  H,B       ;TXTUNF->UNFILLED AREA 
  223.        MOV  L,C 
  224.        SHLD TXTUNF    ;UPDATE
  225. ST4    POP  B         ;GET READY TO INSERT 
  226.        LHLD TXTUNF    ;BUT FIRT CHECK IF
  227.        POP  PSW       ;THE LENGTH OF NEW LINE
  228.        PUSH H         ;IS 3 (LINE # AND CR)
  229.        CPI  3         ;THEN DO NOT INSERT
  230.        JZ   RSTART    ;MUST CLEAR THE STACK
  231.        ADD  L         ;COMPUTE NEW TXTUNF
  232.        MOV  L,A 
  233.        MVI  A,0 
  234.        ADC  H 
  235.        MOV  H,A       ;HL->NEW UNFILLED AREA 
  236. ST4A   LXI  D,TXTEND  ;CHECK TO SEE IF THERE 
  237.        RST  4         ;IS ENOUGH SPACE 
  238.        JNC  QSORRY    ;SORRY, NO ROOM FOR IT 
  239.        SHLD TXTUNF    ;OK, UPDATE TXTUNF 
  240.        POP  D         ;DE->OLD UNFILLED AREA 
  241.        CALL MVDOWN
  242.        POP  D         ;DE->BEGIN, HL->END
  243.        POP  H 
  244.        CALL MVUP      ;MOVE NEW LINE TO SAVE 
  245.        JMP  ST3       ;AREA
  246. ;* 
  247. ;**************************************************************
  248. ;* 
  249. ;* *** TABLES *** DIRECT *** & EXEC ***
  250. ;* 
  251. ;* THIS SECTION OF THE CODE TESTS A STRING AGAINST A TABLE.
  252. ;* WHEN A MATCH IS FOUND, CONTROL IS TRANSFERED TO THE SECTION 
  253. ;* OF CODE ACCORDING TO THE TABLE. 
  254. ;* 
  255. ;* AT 'EXEC', DE SHOULD POINT TO THE STRING AD HL SHOULD POINT
  256. ;* TO THE TABLE-1.  AT 'DIRECT', DE SHOULD POINT TO THE STRING,
  257. ;* HL WILL BE SET UP TO POINT TO TAB1-1, WHICH IS THE TABLE OF 
  258. ;* ALL DIRECT AND STATEMENT COMMANDS.
  259. ;* 
  260. ;* A '.' IN THE STRING WILL TERMINATE THE TEST AND THE PARTIAL 
  261. ;* MATCH WILL BE CONSIDERED AS A MATCH.  E.G., 'P.', 'PR.',
  262. ;* 'PRI.', 'PRIN.', OR 'PRINT' WILL ALL MATCH 'PRINT'. 
  263. ;* 
  264. ;* THE TABLE CONSISTS OF ANY NUMBER OF ITEMS.  EACH ITEM 
  265. ;* IS A STRING OF CHARACTERS WITH BIT 7 SET TO 0 AND 
  266. ;* A JUMP ADDRESS STORED HI-LOW WITH BIT 7 OF THE HIGH 
  267. ;* BYTE SET TO 1.
  268. ;* 
  269. ;* END OF TABLE IS AN ITEM WITH A JUMP ADDRESS ONLY.  IFF THE 
  270. ;* STRING DOES NOT MATCH ANY OF THE OTHER ITEMS, IT WILL 
  271. ;* MATCH THIS NULL ITEM AS DEFAULT.
  272. ;* 
  273. TAB1   EQU  $         ;DIRECT COMMANDS 
  274.        DB   'LIST'
  275.        DB   LIST SHR 8 + 128,LIST AND 0FFH
  276.        DB   'RUN'
  277.        DB   RUN SHR 8 + 128,RUN AND 255
  278.        DB   'NEW'
  279.        DB   NEW SHR 8 + 128,NEW AND 255
  280.        DB   'LOAD'
  281.        DB   DLOAD SHR 8 + 128,DLOAD AND 255
  282.        DB   'SAVE'
  283.        DB   DSAVE SHR 8 + 128,DSAVE AND 255
  284.        DB   'BYE',80H,0H   ;GO BACK TO CPM
  285. TAB2   EQU  $         ;DIRECT/TATEMENT
  286.        DB   'NEXT'
  287.        DB   NEXT SHR 8 + 128,NEXT AND 255
  288.        DB   'LET'
  289.        DB   LET SHR 8 + 128,LET AND 255
  290.        DB   'OUT'
  291.        DB   OUTCMD SHR 8 + 128,OUTCMD AND 255 
  292.        DB   'POKE'
  293.        DB   POKE SHR 8 + 128,POKE AND 255
  294.        DB   'WAIT'
  295.        DB   WAITCM SHR 8 + 128,WAITCM AND 255
  296.        DB   'IF'
  297.        DB   IFF SHR 8 + 128,IFF AND 255
  298.        DB   'GOTO'
  299.        DB   GOTO SHR 8 + 128,GOTO AND 255
  300.        DB   'GOSUB'
  301.        DB   GOSUB SHR 8 + 128,GOSUB AND 255
  302.        DB   'RETURN'
  303.        DB   RETURN SHR 8 + 128,RETURN AND 255
  304.        DB   'REM'
  305.        DB   REM SHR 8 + 128,REM AND 255
  306.        DB   'FOR'
  307.        DB   FOR SHR 8 + 128,FOR AND 255
  308.        DB   'INPUT'
  309.        DB   INPUT SHR 8 + 128,INPUT AND 255
  310.        DB   'PRINT'
  311.        DB   PRINT SHR 8 + 128,PRINT AND 255
  312.        DB   'STOP'
  313.        DB   STOP SHR 8 + 128,STOP AND 255
  314.        DB   DEFLT SHR 8 + 128,DEFLT AND 255
  315.        DB   'YOU CAN ADD MORE' ;COMMANDS BUT
  316.             ;REMEMBER TO MOVE DEFAULT DOWN.
  317. TAB4   EQU  $         ;FUNCTIONS 
  318.        DB   'RND'
  319.        DB   RND SHR 8 + 128,RND AND 255
  320.        DB   'INP'
  321.        DB   INP SHR 8 + 128,INP AND 255
  322.        DB   'PEEK'
  323.        DB   PEEK SHR 8 + 128,PEEK AND 255
  324.        DB   'USR'
  325.        DB   USR SHR 8 + 128,USR AND 255
  326.        DB   'ABS'
  327.        DB   ABS SHR 8 + 128,ABS AND 255
  328.        DB   'SIZE'
  329.        DB   SIZE SHR 8 + 128,SIZE AND 255
  330.        DB   XP40 SHR 8 + 128,XP40 AND 255
  331.        DB   'YOU CAN ADD MORE' ;FUNCTIONS BUT REMEMBER
  332.                       ;TO MOVE XP40 DOWN
  333. TAB5   EQU  $         ;"TO" IN "FOR" 
  334.        DB   'TO'
  335.        DB   FR1 SHR 8 + 128,FR1 AND 255
  336.        DB   QWHAT SHR 8 + 128,QWHAT AND 255
  337. TAB6   EQU  $         ;"STEP" IN "FOR" 
  338.        DB   'STEP'
  339.        DB   FR2 SHR 8 + 128,FR2 AND 255
  340.        DB   FR3 SHR 8 + 128,FR3 AND 255
  341. TAB8   EQU  $         ;RELATION OPERATORS
  342.        DB   '>='
  343.        DB   XP11 SHR 8 + 128,XP11 AND 255
  344.        DB   '#'
  345.        DB   XP12 SHR 8 + 128,XP12 AND 255
  346.        DB   '>'
  347.        DB   XP13 SHR 8 + 128,XP13 AND 255
  348.        DB   '='
  349.        DB   XP15 SHR 8 + 128,XP15 AND 255
  350.        DB   '<='
  351.        DB   XP14 SHR 8 + 128,XP14 AND 255
  352.        DB   '<'
  353.        DB   XP16 SHR 8 + 128,XP16 AND 255
  354.        DB   XP17 SHR 8 + 128,XP17 AND 255
  355. ;* 
  356. DIRECT LXI  H,TAB1-1  ;*** DIRECT ***
  357. ;* 
  358. EXEC   EQU  $         ;*** EXEC ***
  359. EX0    RST  5         ;IGNORE LEADING BLANKS 
  360.        PUSH D         ;SAVE POINTER
  361. EX1    LDAX D         ;IFF FOUND '.' IN STRING
  362.        INX  D         ;BEFORE ANY MISMATCH 
  363.        CPI  56Q       ;WE DECLARE A MATCH
  364.        JZ   EX3 
  365.        INX  H         ;HL->TABLE 
  366.        CMP  M         ;IFF MATCH, TEST NEXT 
  367.        JZ   EX1 
  368.        MVI  A,177Q    ;ELSE, SEE IFF BIT 7
  369.        DCX  D         ;OF TABLEIS SET, WHICH
  370.        CMP  M         ;IS THE JUMP ADDR. (HI)
  371.        JC   EX5       ;C:YES, MATCHED
  372. EX2    INX  H         ;NC:NO, FIND JUMP ADDR.
  373.        CMP  M 
  374.        JNC  EX2 
  375.        INX  H         ;BUMP TO NEXT TAB. ITEM
  376.        POP  D         ;RESTORE STRING POINTER
  377.        JMP  EX0       ;TEST AGAINST NEXT ITEM
  378. EX3    MVI  A,177Q    ;PARTIAL MATCH, FIND 
  379. EX4    INX  H         ;JUMP ADDR., WHICH IS
  380.        CMP  M         ;FLAGGED BY BIT 7
  381.        JNC  EX4 
  382. EX5    MOV  A,M       ;LOAD HL WITH THE JUMP 
  383.        INX  H         ;ADDRESS FROM THE TABLE
  384.        MOV  L,M 
  385.        ANI  177Q      ;MASK OFF BIT 7
  386.        MOV  H,A 
  387.        POP  PSW       ;CLEAN UP THE GABAGE 
  388.        PCHL           ;AND WE GO DO IT 
  389. ;* 
  390. ;**************************************************************
  391. ;* 
  392. ;* WHAT FOLLOWS IS THE CODE TO EXECUTE DIRECT AND STATEMENT
  393. ;* COMMANDS.  CONTROL IS TRANSFERED TO THESE POINTS VIA THE
  394. ;* COMMAND TABLE LOOKUP CODE OF 'DIRECT' AND 'EXEC' IN LAST
  395. ;* SECTION.  AFTER THE COMMAND IS EXECUTED, CONTROL IS 
  396. ;* TANSFERED TO OTHER SECTIONS AS FOLLOWS:
  397. ;* 
  398. ;* FOR 'LIST', 'NEW', AND 'STOP': GO BACK TO 'RSTART'
  399. ;* FOR 'RUN': GO EXECUTE THE FIRST STORED LINE IFF ANY; ELSE
  400. ;* GO BACK TO 'RSTART'.
  401. ;* FOR 'GOTO' AND 'GOSUB': GO EXECUTE THE TARGET LINE. 
  402. ;* FOR 'RETURN' AND 'NEXT': GO BACK TO SAVED RETURN LINE.
  403. ;* FOR ALL OTHERS: IFF 'CURRNT' -> 0, GO TO 'RSTART', ELSE
  404. ;* GO EXECUTE NEXT COMMAND.  (THIS IS DONE IN 'FINISH'.) 
  405. ;* 
  406. ;**************************************************************
  407. ;* 
  408. ;* *** NEW *** STOP *** RUN (& FRIENDS) *** & GOTO *** 
  409. ;* 
  410. ;* 'NEW(CR)' SETS 'TXTUNF' TO POINT TO 'TXTBGN'
  411. ;* 
  412. ;* 'STOP(CR)' GOES BACK TO 'RSTART'
  413. ;* 
  414. ;* 'RUN(CR)' FINDS THE FIRST STORED LINE, STORE ITS ADDRESS (IN
  415. ;* 'CURRNT'), AND START EXECUTE IT.  NOTE THAT ONLY THOSE
  416. ;* COMMANDS IN TAB2 ARE LEGAL FOR STORED PROGRAM.
  417. ;* 
  418. ;* THERE ARE 3 MORE ENTRIES IN 'RUN':
  419. ;* 'RUNNXL' FINDS NEXT LINE, STORES ITS ADDR. AND EXECUTES IT. 
  420. ;* 'RUNTSL' STORES THE ADDRESS OF THIS LINE AND EXECUTES IT. 
  421. ;* 'RUNSML' CONTINUES THE EXECUTION ON SAME LINE.
  422. ;* 
  423. ;* 'GOTO EXPR(CR)' EVALUATES THE EXPRESSION, FIND THE TARGET 
  424. ;* LINE, AND JUMP TO 'RUNTSL' TO DO IT.
  425. ;* 'DLOAD' LOADS A NAMED PROGRAM FROM DISK.
  426. ;* 'DSAVE' SAVES A NAMED PROGRAM ON DISK.
  427. ;* 'FCBSET' SETS UP THE FILE CONTROL BLOCK FOR SUBSEQUENT DISK I/O.
  428. ;* 
  429. NEW    CALL ENDCHK    ;*** NEW(CR) *** 
  430.        LXI  H,TXTBGN
  431.        SHLD TXTUNF
  432. ;* 
  433. STOP   CALL ENDCHK    ;*** STOP(CR) ***
  434.        JMP RSTART
  435. ;* 
  436. RUN    CALL ENDCHK    ;*** RUN(CR) *** 
  437.        LXI  D,TXTBGN  ;FIRST SAVED LINE
  438. ;* 
  439. RUNNXL LXI  H,0       ;*** RUNNXL ***
  440.        CALL FNDLNP    ;FIND WHATEVER LINE #
  441.        JC   RSTART    ;C:PASSED TXTUNF, QUIT 
  442. ;* 
  443. RUNTSL XCHG           ;*** RUNTSL ***
  444.        SHLD CURRNT    ;SET 'CURRNT'->LINE #
  445.        XCHG 
  446.        INX  D         ;BUMP PASS LINE #
  447.        INX  D 
  448. ;* 
  449. RUNSML CALL CHKIO     ;*** RUNSML ***
  450.        LXI  H,TAB2-1  ;FIND COMMAND IN TAB2
  451.        JMP  EXEC      ;AND EXECUTE IT
  452. ;* 
  453. GOTO   RST  3         ;*** GOTO EXPR *** 
  454.        PUSH D         ;SAVE FOR ERROR ROUTINE
  455.        CALL ENDCHK    ;MUST FIND A 0DH
  456.        CALL FNDLN     ;FIND THE TARGET LINE
  457.        JNZ  AHOW      ;NO SUCH LINE #
  458.        POP  PSW       ;CLEAR THE "PUSH DE" 
  459.        JMP  RUNTSL    ;GO DO IT
  460. CPM    EQU  5         ;DISK PARAMETERS
  461. FCB    EQU  5CH
  462. SETDMA EQU  26
  463. OPEN   EQU  15
  464. READD  EQU  20
  465. WRITED EQU  21
  466. CLOSE  EQU  16
  467. MAKE   EQU  22
  468. DELETE EQU  19
  469. ;*
  470. DLOAD  RST  5         ;IGNORE BLANKS
  471.        PUSH H         ;SAVE H
  472.        CALL FCBSET    ;SET UP FILE CONTROL BLOCK
  473.        PUSH D         ;SAVE THE REST
  474.        PUSH B         
  475.        LXI  D,FCB     ;GET FCB ADDRESS
  476.        MVI  C,OPEN    ;PREPARE TO OPEN FILE
  477.        CALL CPM       ;OPEN IT
  478.        CPI  0FFH      ;IS IT THERE?
  479.        JZ   QHOW      ;NO, SEND ERROR
  480.        XRA  A         ;CLEAR A
  481.        STA  FCB+32    ;START AT RECORD 0
  482.        LXI  D,TXTUNF  ;GET BEGINNING
  483. LOAD   PUSH D         ;SAVE DMA ADDRESS
  484.        MVI  C,SETDMA  ;
  485.        CALL CPM       ;SET DMA ADDRESS
  486.        MVI  C,READD   ;
  487.        LXI  D,FCB
  488.        CALL CPM       ;READ SECTOR
  489.        CPI  1         ;DONE?
  490.        JC   RDMORE    ;NO, READ MORE
  491.        JNZ  QHOW      ;BAD READ
  492.        MVI  C,CLOSE
  493.        LXI  D,FCB 
  494.        CALL CPM       ;CLOSE FILE
  495.        POP  D         ;THROW AWAY DMA ADD.
  496.        POP  B         ;GET OLD REGISTERS BACK
  497.        POP  D
  498.        POP  H
  499.        RST  6         ;FINISH
  500. RDMORE POP  D         ;GET DMA ADDRESS
  501.        LXI  H,80H     ;GET 128
  502.        DAD  D         ;ADD 128 TO DMA ADD.
  503.        XCHG           ;PUT IT BACK IN D
  504.        JMP  LOAD      ;AND READ SOME MORE
  505. ;*
  506. DSAVE  RST  5         ;IGNORE BLANKS
  507.        PUSH H         ;SAVE H
  508.        CALL FCBSET    ;SETUP FCB
  509.        PUSH D
  510.        PUSH B         ;SAVE OTHERS
  511.        LXI  D,FCB
  512.        MVI  C,DELETE
  513.        CALL CPM       ;ERASE FILE IF IT EXISTS
  514.        LXI  D,FCB  
  515.        MVI  C,MAKE
  516.        CALL CPM       ;MAKE A NEW ONE
  517.        CPI  0FFH      ;IS THERE SPACE?
  518.        JZ   QHOW      ;NO, ERROR
  519.        XRA  A         ;CLEAR A
  520.        STA  FCB+32    ;START AT RECORD 0
  521.        LXI  D,TXTUNF  ;GET BEGINNING
  522. SAVE   PUSH D         ;SAVE DMA ADDRESS
  523.        MVI  C,SETDMA  ;
  524.        CALL CPM       ;SET DMA ADDRESS
  525.        MVI  C,WRITED
  526.        LXI  D,FCB 
  527.        CALL CPM       ;WRITE SECTOR
  528.        ORA  A         ;SET FLAGS
  529.        JNZ  QHOW      ;IF NOT ZERO, ERROR
  530.        POP  D         ;GET DMA ADD. BACK
  531.        LDA  TXTUNF+1  ;AND MSB OF LAST ADD.
  532.        CMP  D         ;IS D SMALLER?
  533.        JC   SAVDON    ;YES, DONE
  534.        JNZ  WRITMOR   ;DONT TEST E IF NOT EQUAL
  535.        LDA  TXTUNF    ;IS E SMALLER?
  536.        CMP  E
  537.        JC   SAVDON    ;YES, DONE
  538. WRITMOR LXI  H,80H 
  539.        DAD  D         ;ADD 128 TO DMA ADD.
  540.        XCHG           ;GET IT BACK IN D
  541.        JMP  SAVE      ;WRITE SOME MORE
  542. SAVDON MVI  C,CLOSE
  543.        LXI  D,FCB 
  544.        CALL CPM       ;CLOSE FILE
  545.        POP  B         ;GET REGISTERS BACK
  546.        POP  D
  547.        POP  H
  548.        RST  6         ;FINISH
  549. ;*
  550. FCBSET LXI  H,FCB     ;GET FILE CONTROL BLOCK ADDRESS
  551.        MVI  M,0       ;CLEAR ENTRY TYPE
  552. FNCLR  INX  H         ;NEXT LOCATION
  553.        MVI  M,' '     ;CLEAR TO SPACE
  554.        MVI  A,FCB+8 AND 255
  555.        CMP  L         ;DONE?
  556.        JNZ  FNCLR     ;NO, DO IT AGAIN
  557.        INX  H         ;NEXT
  558.        MVI  M,'T'     ;SET FILE TYPE TO 'TBI'
  559.        INX  H
  560.        MVI  M,'B'
  561.        INX  H
  562.        MVI  M,'I'
  563. EXRC   INX  H         ;CLEAR REST OF FCB
  564.        MVI  M,0
  565.        MVI  A,FCB+15 AND 255
  566.        CMP  L         ;DONE?
  567.        JNZ  EXRC      ;NO, CONTINUE
  568.        LXI  H,FCB+1   ;GET FILENAME START
  569. FN     LDAX D         ;GET CHARACTER
  570.        CPI  0DH       ;IS IT A 'CR'
  571.        RZ             ;YES, DONE
  572.        CPI  '!'       ;LEGAL CHARACTER?
  573.        JC   QWHAT     ;NO, SEND ERROR
  574.        CPI  '['       ;AGAIN
  575.        JNC  QWHAT     ;DITTO
  576.        MOV  M,A        ;SAVE IT IN FCB
  577.        INX  H         ;NEXT
  578.        INX  D
  579.        MVI  A,FCB+9 AND 255
  580.        CMP  L         ;LAST?
  581.        JNZ  FN        ;NO, CONTINUE
  582.        RET            ;TRUNCATE AT 8 CHARACTERS
  583. ;* 
  584. ;************************************************************* 
  585. ;* 
  586. ;* *** LIST *** & PRINT ***
  587. ;* 
  588. ;* LIST HAS TWO FORMS: 
  589. ;* 'LIST(CR)' LISTS ALL SAVED LINES
  590. ;* 'LIST #(CR)' START LIST AT THIS LINE #
  591. ;* YOU CAN STOP THE LISTING BY CONTROL C KEY 
  592. ;* 
  593. ;* PRINT COMMAND IS 'PRINT ....;' OR 'PRINT ....(CR)'
  594. ;* WHERE '....' IS A LIST OF EXPRESIONS, FORMATS, BACK-
  595. ;* ARROWS, AND STRINGS.  THESE ITEMS ARE SEPERATED BY COMMAS.
  596. ;* 
  597. ;* A FORMAT IS A POUND SIGN FOLLOWED BY A NUMBER.  IT CONTROLSs 
  598. ;* THE NUMBER OF SPACES THE VALUE OF A EXPRESION IS GOING TO 
  599. ;* BE PRINTED.  IT STAYS EFFECTIVE FOR THE REST OF THE PRINT 
  600. ;* COMMAND UNLESS CHANGED BY ANOTHER FORMAT.  IFF NO FORMAT IS
  601. ;* SPECIFIED, 6 POSITIONS WILL BE USED.
  602. ;* 
  603. ;* A STRING IS QUOTED IN A PAIR OF SINGLE QUOTES OR A PAIR OF
  604. ;* DOUBLE QUOTES.
  605. ;* 
  606. ;* A BACK-ARROW MEANS GENERATE A (CR) WITHOUT (LF) 
  607. ;* 
  608. ;* A (CRLF) IS GENERATED AFTER THE ENTIRE LIST HAS BEEN
  609. ;* PRINTED OR IFF THE LIST IS A NULL LIST.  HOWEVER IFF THE LIST 
  610. ;* ENDED WITH A COMMA, NO (CRL) IS GENERATED. 
  611. ;* 
  612. LIST   CALL TSTNUM    ;TEST IFF THERE IS A #
  613.        CALL ENDCHK    ;IFF NO # WE GET A 0
  614.        CALL FNDLN     ;FIND THIS OR NEXT LINE
  615. LS1    JC   RSTART    ;C:PASSED TXTUNF 
  616.        CALL PRTLN     ;PRINT THE LINE
  617.        CALL CHKIO     ;STOP IFF HIT CONTROL-C 
  618.        CALL FNDLNP    ;FIND NEXT LINE
  619.        JMP  LS1       ;AND LOOP BACK 
  620. ;* 
  621. PRINT  MVI  C,6       ;C = # OF SPACES 
  622.        RST  1         ;IFF NULL LIST & ";"
  623.        DB   73Q 
  624.        DB   6Q 
  625.        CALL CRLF      ;GIVE CR-LF AND
  626.        JMP  RUNSML    ;CONTINUE SAME LINE
  627. PR2    RST  1         ;IFF NULL LIST (CR) 
  628.        DB   0DH
  629.        DB   6Q
  630.        CALL CRLF      ;ALSO GIVE CR-LF AND 
  631.        JMP  RUNNXL    ;GO TO NEXT LINE 
  632. PR0    RST  1         ;ELSE IS IT FORMAT?
  633.        DB   '#' 
  634.        DB   5Q
  635.        RST  3         ;YES, EVALUATE EXPR. 
  636.        MOV  C,L       ;AND SAVE IT IN C
  637.        JMP  PR3       ;LOOK FOR MORE TO PRINT
  638. PR1    CALL QTSTG     ;OR IS IT A STRING?
  639.        JMP  PR8       ;IFF NOT, MUST BE EXPR. 
  640. PR3    RST  1         ;IFF ",", GO FIND NEXT
  641.        DB   ',' 
  642.        DB   6Q
  643.        CALL FIN       ;IN THE LIST.
  644.        JMP  PR0       ;LIST CONTINUES
  645. PR6    CALL CRLF      ;LIST ENDS 
  646.        RST  6 
  647. PR8    RST  3         ;EVALUATE THE EXPR 
  648.        PUSH B 
  649.        CALL PRTNUM    ;PRINT THE VALUE 
  650.        POP  B 
  651.        JMP  PR3       ;MORE TO PRINT?
  652. ;* 
  653. ;**************************************************************
  654. ;* 
  655. ;* *** GOSUB *** & RETURN ***
  656. ;* 
  657. ;* 'GOSUB EXPR;' OR 'GOSUB EXPR (CR)' IS LIKE THE 'GOTO' 
  658. ;* COMMAND, EXCEPT THAT THE CURRENT TEXT POINTER, STACK POINTER
  659. ;* ETC. ARE SAVE SO THAT EXECUTION CAN BE CONTINUED AFTER THE
  660. ;* SUBROUTINE 'RETURN'.  IN ORDER THAT 'GOSUB' CAN BE NESTED 
  661. ;* (AND EVEN RECURSIVE), THE SAVE AREA MUST BE STACKED.
  662. ;* THE STACK POINTER IS SAVED IN 'STKGOS'. THE OLD 'STKGOS' IS 
  663. ;* SAVED IN THE STACK.  IFF WE ARE IN THE MAIN ROUTINE, 'STKGOS'
  664. ;* IS ZERO (THIS WAS DONE BY THE "MAIN" SECTION OF THE CODE),
  665. ;* BUT WE STILL SAVE IT AS A FLAG FORr NO FURTHER 'RETURN'S.
  666. ;* 
  667. ;* 'RETURN(CR)' UNDOS EVERYHING THAT 'GOSUB' DID, AND THUS
  668. ;* RETURN THE EXCUTION TO THE COMMAND AFTER THE MOST RECENT
  669. ;* 'GOSUB'.  IFF 'STKGOS' IS ZERO, IT INDICATES THAT WE 
  670. ;* NEVER HAD A 'GOSUB' AND IS THUS AN ERROR. 
  671. ;* 
  672. GOSUB  CALL PUSHA     ;SAVE THE CURRENT "FOR"
  673.        RST  3         ;PARAMETERS
  674.        PUSH D         ;AND TEXT POINTER
  675.        CALL FNDLN     ;FIND THE TARGET LINE
  676.        JNZ  AHOW      ;NOT THERE. SAY "HOW?" 
  677.        LHLD CURRNT    ;FOUND IT, SAVE OLD
  678.        PUSH H         ;'CURRNT' OLD 'STKGOS' 
  679.        LHLD STKGOS
  680.        PUSH H 
  681.        LXI  H,0       ;AND LOAD NEW ONES 
  682.        SHLD LOPVAR
  683.        DAD  SP
  684.        SHLD STKGOS
  685.        JMP  RUNTSL    ;THEN RUN THAT LINE
  686. RETURN CALL ENDCHK    ;THERE MUST BE A 0DH
  687.        LHLD STKGOS    ;OLD STACK POINTER 
  688.        MOV  A,H       ;0 MEANS NOT EXIST 
  689.        ORA  L 
  690.        JZ   QWHAT     ;SO, WE SAY: "WHAT?" 
  691.        SPHL           ;ELSE, RESTORE IT
  692.        POP  H 
  693.        SHLD STKGOS    ;AND THE OLD 'STKGOS'
  694.        POP  H 
  695.        SHLD CURRNT    ;AND THE OLD 'CURRNT'
  696.        POP  D         ;OLD TEXT POINTER
  697.        CALL POPA      ;OLD "FOR" PARAMETERS
  698.        RST  6         ;AND WE ARE BACK HOME
  699. ;* 
  700. ;**************************************************************
  701. ;* 
  702. ;* *** FOR *** & NEXT ***
  703. ;* 
  704. ;* 'FOR' HAS TWO FORMS:
  705. ;* 'FOR VAR=EXP1 TO EXP2 STEP EXP1' AND 'FOR VAR=EXP1 TO EXP2' 
  706. ;* THE SECOND FORM MEANS THE SAME THING AS THE FIRST FORM WITH 
  707. ;* EXP1=1.  (I.E., WITH A STEP OF +1.) 
  708. ;* TBI WILL FIND THE VARIABLE VAR. AND SET ITS VALUE TO THE
  709. ;* CURRENT VALUE OF EXP1.  IT ALSO EVALUATES EXPR2 AND EXP1
  710. ;* AND SAVE ALL THESE TOGETHER WITH THE TEXT POINTERr ETC. IN 
  711. ;* THE 'FOR' SAVE AREA, WHICH CONSISTS OF 'LOPVAR', 'LOPINC',
  712. ;* 'LOPLMT', 'LOPLN', AND 'LOPPT'.  IFF THERE IS ALREADY SOME-
  713. ;* THING IN THE SAVE AREA (THIS IS INDICATED BY A NON-ZERO 
  714. ;* 'LOPVAR'), THEN THE OLD SAVE AREA IS SAVED IN THE STACK 
  715. ;* BEFORE THE NEW ONE OVERWRITES IT. 
  716. ;* TBI WILL THEN DIG IN THE STACK AND FIND OUT IFF THIS SAME
  717. ;* VARIABLE WAS USED IN ANOTHER CURRENTLY ACTIVE 'FOR' LOOP. 
  718. ;* IFF THAT IS THE CASE THEN THE OLD 'FOR' LOOP IS DEACTIVATED.
  719. ;* (PURGED FROM THE STACK..) 
  720. ;* 
  721. ;* 'NEXT VAR' SERVES AS THE LOGICAL (NOT NECESSARILLY PHYSICAL)
  722. ;* END OF THE 'FOR' LOOP.  THE CONTROL VARIABLE VAR. IS CHECKED
  723. ;* WITH THE 'LOPVAR'.  IFF THEY ARE NOT THE SAME, TBI DIGS IN 
  724. ;* THE STACK TO FIND THE RIGHTt ONE AND PURGES ALL THOSE THAT 
  725. ;* DID NOT MATCH.  EITHER WAY, TBI THEN ADDS THE 'STEP' TO 
  726. ;* THAT VARIABLE AND CHECK THE RESULT WITH THE LIMIT.  IFF IT 
  727. ;* IS WITHIN THE LIMIT, CONTROL LOOPS BACK TO THE COMMAND
  728. ;* FOLLOWING THE 'FOR'.  IFF OUTSIDE THE LIMIT, THE SAVE ARER 
  729. ;* IS PURGED AND EXECUTION CONTINUES.
  730. ;* 
  731. FOR    CALL PUSHA     ;SAVE THE OLD SAVE AREA
  732.        CALL SETVAL    ;SET THE CONTROL VAR.
  733.        DCX  H         ;HL IS ITS ADDRESS 
  734.        SHLD LOPVAR    ;SAVE THAT 
  735.        LXI  H,TAB5-1  ;USE 'EXEC' TO LOOK
  736.        JMP  EXEC      ;FOR THE WORD 'TO' 
  737. FR1    RST  3         ;EVALUATE THE LIMIT
  738.        SHLD LOPLMT    ;SAVE THAT 
  739.        LXI  H,TAB6-1  ;USE 'EXEC' TO LOOK
  740.        JMP  EXEC      ;FOR THE WORD 'STEP'
  741. FR2    RST  3         ;FOUND IT, GET STEP
  742.        JMP  FR4 
  743. FR3    LXI  H,1Q      ;NOT FOUND, SET TO 1 
  744. FR4    SHLD LOPINC    ;SAVE THAT TOO 
  745. FR5    LHLD CURRNT    ;SAVE CURRENT LINE # 
  746.        SHLD LOPLN 
  747.        XCHG           ;AND TEXT POINTER
  748.        SHLD LOPPT 
  749.        LXI  B,12Q     ;DIG INTO STACK TO 
  750.        LHLD LOPVAR    ;FIND 'LOPVAR' 
  751.        XCHG 
  752.        MOV  H,B 
  753.        MOV  L,B       ;HL=0 NOW
  754.        DAD  SP        ;HERE IS THE STACK 
  755.        DB   76Q 
  756. FR7    DAD  B         ;EACH LEVEL IS 10 DEEP 
  757.        MOV  A,M       ;GET THAT OLD 'LOPVAR' 
  758.        INX  H 
  759.        ORA  M 
  760.        JZ   FR8       ;0 SAYS NO MORE IN IT
  761.        MOV  A,M 
  762.        DCX  H 
  763.        CMP  D         ;SAME AS THIS ONE? 
  764.        JNZ  FR7 
  765.        MOV  A,M       ;THE OTHER HALF? 
  766.        CMP  E 
  767.        JNZ  FR7 
  768.        XCHG           ;YES, FOUND ONE
  769.        LXI  H,0Q
  770.        DAD  SP        ;TRY TO MOVE SP
  771.        MOV  B,H 
  772.        MOV  C,L 
  773.        LXI  H,12Q 
  774.        DAD  D 
  775.        CALL MVDOWN    ;AND PURGE 10 WORDS
  776.        SPHL           ;IN THE STACK
  777. FR8    LHLD LOPPT     ;JOB DONE, RESTORE DE
  778.        XCHG 
  779.        RST  6         ;AND CONTINUE
  780. ;* 
  781. NEXT   RST  7         ;GET ADDRESS OF VAR. 
  782.        JC   QWHAT     ;NO VARIABLE, "WHAT?"
  783.        SHLD VARNXT    ;YES, SAVE IT
  784. NX0    PUSH D         ;SAVE TEXT POINTER 
  785.        XCHG 
  786.        LHLD LOPVAR    ;GET VAR. IN 'FOR' 
  787.        MOV  A,H 
  788.        ORA  L         ;0 SAYS NEVER HAD ONE
  789.        JZ   AWHAT     ;SO WE ASK: "WHAT?"
  790.        RST  4         ;ELSE WE CHECK THEM
  791.        JZ   NX3       ;OK, THEY AGREE
  792.        POP  D         ;NO, LET'S SEE 
  793.        CALL POPA      ;PURGE CURRENT LOOP
  794.        LHLD VARNXT    ;AND POP ONE LEVEL 
  795.        JMP  NX0       ;GO CHECK AGAIN
  796. NX3    MOV  E,M       ;COME HERE WHEN AGREED 
  797.        INX  H 
  798.        MOV  D,M       ;DE=VALUE OF VAR.
  799.        LHLD LOPINC
  800.        PUSH H 
  801.        DAD  D         ;ADD ONE STEP
  802.        XCHG 
  803.        LHLD LOPVAR    ;PUT IT BACK 
  804.        MOV  M,E 
  805.        INX  H 
  806.        MOV  M,D 
  807.        LHLD LOPLMT    ;HL->LIMIT 
  808.        POP  PSW       ;OLD HL
  809.        ORA  A 
  810.        JP   NX1       ;STEP > 0
  811.        XCHG 
  812. NX1    CALL CKHLDE    ;COMPARE WITH LIMIT
  813.        POP  D         ;RESTORE TEXT POINTER
  814.        JC   NX2       ;OUTSIDE LIMIT 
  815.        LHLD LOPLN     ;WITHIN LIMIT, GO
  816.        SHLD CURRNT    ;BACK TO THE SAVED 
  817.        LHLD LOPPT     ;'CURRNT' AND TEXT 
  818.        XCHG           ;POINTER 
  819.        RST  6 
  820. NX2    CALL POPA      ;PURGE THIS LOOP 
  821.        RST  6 
  822. ;* 
  823. ;**************************************************************
  824. ;* 
  825. ;* *** REM *** IFF *** INPUT *** & LET (& DEFLT) ***
  826. ;* 
  827. ;* 'REM' CAN BE FOLLOWED BY ANYTHING AND IS IGNORED BY TBI.
  828. ;* TBI TREATS IT LIKE AN 'IF' WITH A FALSE CONDITION.
  829. ;* 
  830. ;* 'IF' IS FOLLOWED BY AN EXPR. AS A CONDITION AND ONE OR MORE 
  831. ;* COMMANDS (INCLUDING OUTHER 'IF'S) SEPERATED BY SEMI-COLONS. 
  832. ;* NOTE THAT THE WORD 'THEN' IS NOT USED.  TBI EVALUATES THE 
  833. ;* EXPR. IFF IT IS NON-ZERO, EXECUTION CONTINUES.  IFF THE 
  834. ;* EXPR. IS ZERO, THE COMMANDS THAT FOLLOWS ARE IGNORED AND
  835. ;* EXECUTION CONTINUES AT THE NEXT LINE. 
  836. ;* 
  837. ;* 'IPUT' COMMAND IS LIKE THE 'PRINT' COMMAND, AND IS FOLLOWED
  838. ;* BY A LIST OF ITEMS.  IFF THE ITEM IS A STRING IN SINGLE OR 
  839. ;* DOUBLE QUOTES, OR IS A BACK-ARROW, IT HAS THE SAME EFFECT AS
  840. ;* IN 'PRINT'.  IFF AN ITEM IS A VARIABLE, THIS VARIABLE NAME IS
  841. ;* PRINTED OUT FOLLOWED BY A COLON.  THEN TBI WAITS FOR AN 
  842. ;* EXPR. TO BE TYPED IN.  THE VARIABLE ISs THEN SET TO THE
  843. ;* VALUE OF THIS EXPR.  IFF THE VARIABLE IS PROCEDED BY A STRING
  844. ;* (AGAIN IN SINGLE OR DOUBLE QUOTES), THE STRING WILL BE
  845. ;* PRINTED FOLLOWED BY A COLON.  TBI THEN WAITS FOR INPUT EXPR.
  846. ;* AND SET THE VARIABLE TO THE VALUE OF THE EXPR.
  847. ;* 
  848. ;* IFF THE INPUT EXPR. IS INVALID, TBI WILL PRINT "WHAT?",
  849. ;* "HOW?" OR "SORRY" AND REPRINT THE PROMPT AND REDO THE INPUT.
  850. ;* THE EXECUTION WILL NOT TERMINATE UNLESS YOU TYPE CONTROL-C. 
  851. ;* THIS IS HANDLED IN 'INPERR'.
  852. ;* 
  853. ;* 'LET' IS FOLLOWED BY A LIST OF ITEMS SEPERATED BY COMMAS. 
  854. ;* EACH ITEM CONSISTS OF A VARIABLE, AN EQUAL SIGN, AND AN EXPR. 
  855. ;* TBI EVALUATES THE EXPR. AND SET THE VARIBLE TO THAT VALUE.
  856. ;* TB WILL ALSO HANDLE 'LET' COMMAND WITHOUT THE WORD 'LET'.
  857. ;* THIS IS DONE BY 'DEFLT'.
  858. ;* 
  859. REM    LXI  H,0Q      ;*** REM *** 
  860.        DB   76Q 
  861. ;* 
  862. IFF     RST  3         ;*** IFF ***
  863.        MOV  A,H       ;IS THE EXPR.=0? 
  864.        ORA  L 
  865.        JNZ  RUNSML    ;NO, CONTINUE
  866.        CALL FNDSKP    ;YES, SKIP REST OF LINE
  867.        JNC  RUNTSL
  868.        JMP  RSTART
  869. ;* 
  870. INPERR LHLD STKINP    ;*** INPERR ***
  871.        SPHL           ;RESTORE OLD SP
  872.        POP  H         ;AND OLD 'CURRNT'
  873.        SHLD CURRNT
  874.        POP  D         ;AND OLD TEXT POINTER
  875.        POP  D         ;REDO INPUT
  876. ;* 
  877. INPUT  EQU  $         ;*** INPUT *** 
  878. IP1    PUSH D         ;SAVE IN CASE OF ERROR 
  879.        CALL QTSTG     ;IS NEXT ITEM A STRING?
  880.        JMP  IP2       ;NO
  881.        RST  7         ;YES. BUT FOLLOWED BY A
  882.        JC   IP4       ;VARIABLE?   NO. 
  883.        JMP  IP3       ;YES.  INPUT VARIABLE
  884. IP2    PUSH D         ;SAVE FOR 'PRTSTG' 
  885.        RST  7         ;MUST BE VARIABLE NOW
  886.        JC   QWHAT     ;"WHAT?" IT IS NOT?
  887.        LDAX D         ;GET READY FOR 'RTSTG'
  888.        MOV  C,A 
  889.        SUB  A 
  890.        STAX D 
  891.        POP  D 
  892.        CALL PRTSTG    ;PRINT STRING AS PROMPT
  893.        MOV  A,C       ;RESTORE TEXT
  894.        DCX  D 
  895.        STAX D 
  896. IP3    PUSH D         ;SAVE IN CASE OF ERROR 
  897.        XCHG 
  898.        LHLD CURRNT    ;ALSO SAVE 'CURRNT'
  899.        PUSH H 
  900.        LXI  H,IP1     ;A NEGATIVE NUMBER 
  901.        SHLD CURRNT    ;AS A FLAG 
  902.        LXI  H,0Q      ;SAVE SP TOO 
  903.        DAD  SP
  904.        SHLD STKINP
  905.        PUSH D         ;OLD HL
  906.        MVI  A,72Q     ;PRINT THIS TOO
  907.        CALL GETLN     ;AND GET A LINE
  908. IP3A   LXI  D,BUFFER  ;POINTS TO BUFFER
  909.        RST  3         ;EVALUATE INPUT
  910.        NOP            ;CAN BE 'CALL ENDCHK'
  911.        NOP
  912.        NOP
  913.        POP  D         ;OK, GET OLD HL
  914.        XCHG 
  915.        MOV  M,E       ;SAVE VALUE IN VAR.
  916.        INX  H 
  917.        MOV  M,D 
  918.        POP  H         ;GET OLD 'CURRNT'
  919.        SHLD CURRNT
  920.        POP  D         ;AND OLD TEXT POINTER
  921. IP4    POP  PSW       ;PURGE JUNK IN STACK 
  922.        RST  1         ;IS NEXT CH. ','?
  923.        DB   ',' 
  924.        DB   3Q
  925.        JMP  IP1       ;YES, MORE ITEMS.
  926. IP5    RST  6 
  927. ;* 
  928. DEFLT  LDAX D         ;*** DEFLT *** 
  929.        CPI  0DH       ;EMPTY LINE IS OK
  930.        JZ   LT1       ;ELSE IT IS 'LET'
  931. ;* 
  932. LET    CALL SETVAL    ;*** LET *** 
  933.        RST  1         ;SET VALUE TO VAR. 
  934.        DB   ',' 
  935.        DB   3Q
  936.        JMP  LET       ;ITEM BY ITEM
  937. LT1    RST  6         ;UNTIL FINISH
  938. ;* 
  939. ;**************************************************************
  940. ;* 
  941. ;* *** EXPR ***
  942. ;* 
  943. ;* 'EXPR' EVALUATES ARITHMETICAL OR LOGICAL EXPRESSIONS. 
  944. ;* <EXPR>::=<EXPR2>
  945. ;*          <EXPR2><REL.OP.><EXPR2>
  946. ;* WHERE <REL.OP.> IS ONE OF THE OPERATORSs IN TAB8 AND THE 
  947. ;* RESULT OF THESE OPERATIONS IS 1 IFF TRUE AND 0 IFF FALSE. 
  948. ;* <EXPR2>::=(+ OR -)<EXPR3>(+ OR -<EXPR3>)(....)
  949. ;* WHERE () ARE OPTIONAL AND (....) ARE OPTIONAL REPEATS.
  950. ;* <EXPR3>::=<EXPR4>(<* OR /><EXPR4>)(....)
  951. ;* <EXPR4>::=<VARIABLE>
  952. ;*           <FUNCTION>
  953. ;*           (<EXPR>)
  954. ;* <EXPR> IS RECURSIVE SO THAT VARIABLE '@' CAN HAVE AN <EXPR> 
  955. ;* AS INDEX, FNCTIONS CAN HAVE AN <EXPR> AS ARGUMENTS, AND
  956. ;* <EXPR4> CAN BE AN <EXPR> IN PARANTHESE. 
  957. ;* 
  958. ;*                 EXPR   CALL EXPR2     THIS IS AT LOC. 18
  959. ;*                        PUSH HL        SAVE <EXPR2> VALUE
  960. EXPR1  LXI  H,TAB8-1  ;LOOKUP REL.OP.
  961.        JMP  EXEC      ;GO DO IT
  962. XP11   CALL XP18      ;REL.OP.">=" 
  963.        RC             ;NO, RETURN HL=0 
  964.        MOV  L,A       ;YES, RETURN HL=1
  965.        RET
  966. XP12   CALL XP18      ;REL.OP."#"
  967.        RZ             ;FALSE, RETURN HL=0
  968.        MOV  L,A       ;TRUE, RETURN HL=1 
  969.        RET
  970. XP13   CALL XP18      ;REL.OP.">"
  971.        RZ             ;FALSE 
  972.        RC             ;ALSO FALSE, HL=0
  973.        MOV  L,A       ;TRUE, HL=1
  974.        RET
  975. XP14   CALL XP18      ;REL.OP."<=" 
  976.        MOV  L,A       ;SET HL=1
  977.        RZ             ;REL. TRUE, RETURN 
  978.        RC 
  979.        MOV  L,H       ;ELSE SET HL=0 
  980.        RET
  981. XP15   CALL XP18      ;REL.OP."="
  982.        RNZ            ;FALSE, RETRUN HL=0
  983.        MOV  L,A       ;ELSE SET HL=1 
  984.        RET
  985. XP16   CALL XP18      ;REL.OP."<"
  986.        RNC            ;FALSE, RETURN HL=0
  987.        MOV  L,A       ;ELSE SET HL=1 
  988.        RET
  989. XP17   POP  H         ;NOT REL.OP. 
  990.        RET            ;RETURN HL=<EXPR2> 
  991. XP18   MOV  A,C       ;SUBROUTINE FOR ALL
  992.        POP  H         ;REL.OP.'S 
  993.        POP  B 
  994.        PUSH H         ;REVERSE TOP OF STACK
  995.        PUSH B 
  996.        MOV  C,A 
  997.        CALL EXPR2     ;GET 2ND <EXPR2> 
  998.        XCHG           ;VALUE IN DE NOW 
  999.        XTHL           ;1ST <EXPR2> IN HL 
  1000.        CALL CKHLDE    ;COMPARE 1ST WITH 2ND
  1001.        POP  D         ;RESTORE TEXT POINTER
  1002.        LXI  H,0Q      ;SET HL=0, A=1 
  1003.        MVI  A,1 
  1004.        RET
  1005. ;* 
  1006. EXPR2  RST  1         ;NEGATIVE SIGN?
  1007.        DB   '-' 
  1008.        DB   6Q
  1009.        LXI  H,0Q      ;YES, FAKE '0-'
  1010.        JMP  XP26      ;TREAT LIKE SUBTRACT 
  1011. XP21   RST  1         ;POSITIVE SIGN?  IGNORE
  1012.        DB   '+' 
  1013.        DB   0Q
  1014. XP22   CALL EXPR3     ;1ST <EXPR3> 
  1015. XP23   RST  1         ;ADD?
  1016.        DB   '+' 
  1017.        DB   25Q 
  1018.        PUSH H         ;YES, SAVE VALUE 
  1019.        CALL EXPR3     ;GET 2ND<EXPR3> 
  1020. XP24   XCHG           ;2ND IN DE 
  1021.        XTHL           ;1ST IN HL 
  1022.        MOV  A,H       ;COMPARE SIGN
  1023.        XRA  D 
  1024.        MOV  A,D 
  1025.        DAD  D 
  1026.        POP  D         ;RESTORE TEXT POINTER
  1027.        JM   XP23      ;1ST 2ND SIGN DIFFER 
  1028.        XRA  H         ;1ST 2ND SIGN EQUAL
  1029.        JP   XP23      ;SO ISp RESULT
  1030.        JMP  QHOW      ;ELSE WE HAVE OVERFLOW 
  1031. XP25   RST  1         ;SUBTRACT? 
  1032.        DB   '-' 
  1033.        DB   203Q
  1034. XP26   PUSH H         ;YES, SAVE 1ST <EXPR3> 
  1035.        CALL EXPR3     ;GET 2ND <EXPR3> 
  1036.        CALL CHGSGN    ;NEGATE
  1037.        JMP  XP24      ;AND ADD THEM
  1038. ;* 
  1039. EXPR3  CALL EXPR4     ;GET 1ST <EXPR4> 
  1040. XP31   RST  1         ;MULTIPLY? 
  1041.        DB   '*' 
  1042.        DB   54Q 
  1043.        PUSH H         ;YES, SAVE 1ST 
  1044.        CALL EXPR4     ;AND GET 2ND <EXPR4> 
  1045.        MVI  B,0Q      ;CLEAR B FOR SIGN
  1046.        CALL CHKSGN    ;CHECK SIGN
  1047.        XCHG           ;2ND IN DE NOW 
  1048.        XTHL           ;1ST IN HL 
  1049.        CALL CHKSGN    ;CHECK SIGN OF 1ST 
  1050.        MOV  A,H       ;IS HL > 255 ? 
  1051.        ORA  A 
  1052.        JZ   XP32      ;NO
  1053.        MOV  A,D       ;YES, HOW ABOUT DE 
  1054.        ORA  D 
  1055.        XCHG           ;PUT SMALLER IN HL 
  1056.        JNZ  AHOW      ;ALSO >, WILL OVERFLOW 
  1057. XP32   MOV  A,L       ;THIS IS DUMB
  1058.        LXI  H,0Q      ;CLEAR RESULT
  1059.        ORA  A         ;ADD AND COUNT 
  1060.        JZ   XP35
  1061. XP33   DAD  D 
  1062.        JC   AHOW      ;OVERFLOW
  1063.        DCR  A 
  1064.        JNZ  XP33
  1065.        JMP  XP35      ;FINISHED
  1066. XP34   RST  1         ;DIVIDE? 
  1067.        DB   '/' 
  1068.        DB   104Q
  1069.        PUSH H         ;YES, SAVE 1ST <EXPR4> 
  1070.        CALL EXPR4     ;AND GET 2ND ONE 
  1071.        MVI  B,0Q      ;CLEAR B FOR SIGN
  1072.        CALL CHKSGN    ;CHECK SIGN OF 2ND 
  1073.        XCHG           ;PUT 2ND IN DE 
  1074.        XTHL           ;GET 1ST IN HL 
  1075.        CALL CHKSGN    ;CHECK SIGN OF 1ST 
  1076.        MOV  A,D       ;DIVIDE BY 0?
  1077.        ORA  E 
  1078.        JZ   AHOW      ;SAY "HOW?"
  1079.        PUSH B         ;ELSE SAVE SIGN
  1080.        CALL DIVIDE    ;USE SUBROUTINE
  1081.        MOV  H,B       ;RESULT IN HL NOW
  1082.        MOV  L,C 
  1083.        POP  B         ;GET SIGN BACK 
  1084. XP35   POP  D         ;AND TEXT POINTER
  1085.        MOV  A,H       ;HL MUST BE +
  1086.        ORA  A 
  1087.        JM   QHOW      ;ELSE IT IS OVERFLOW 
  1088.        MOV  A,B 
  1089.        ORA  A 
  1090.        CM   CHGSGN    ;CHANGE SIGN IFF NEEDED 
  1091.        JMP  XP31      ;LOOK OR MORE TERMS 
  1092. ;* 
  1093. EXPR4  LXI  H,TAB4-1  ;FIND FUNCTION IN TAB4 
  1094.        JMP  EXEC      ;AND GO DO IT
  1095. XP40   RST  7         ;NO, NOT A FUNCTION
  1096.        JC   XP41      ;NOR A VARIABLE
  1097.        MOV  A,M       ;VARIABLE
  1098.        INX  H 
  1099.        MOV  H,M       ;VALUE IN HL 
  1100.        MOV  L,A 
  1101.        RET
  1102. XP41   CALL TSTNUM    ;OR IS IT A NUMBER 
  1103.        MOV  A,B       ;# OF DIGIT
  1104.        ORA  A 
  1105.        RNZ            ;OK
  1106. PARN   RST  1         ;NO DIGIT, MUST BE 
  1107.        DB   '(' 
  1108.        DB   5Q
  1109.        RST  3         ;"(EXPR)"
  1110.        RST  1 
  1111.        DB   ')' 
  1112.        DB   1Q
  1113. XP42   RET
  1114. XP43   JMP  QWHAT     ;ELSE SAY: "WHAT?" 
  1115. ;* 
  1116. RND    CALL PARN      ;*** RND(EXPR) *** 
  1117.        MOV  A,H       ;EXPR MUST BE +
  1118.        ORA  A 
  1119.        JM   QHOW
  1120.        ORA  L         ;AND NON-ZERO
  1121.        JZ   QHOW
  1122.        PUSH D         ;SAVE BOTH 
  1123.        PUSH H 
  1124.        LHLD RANPNT    ;GET MEMORY AS RANDOM
  1125.        LXI  D,LSTROM  ;NUMBER
  1126.        RST  4 
  1127.        JC   RA1       ;WRAP AROUND IFF LAST 
  1128.        LXI  H,START 
  1129. RA1    MOV  E,M 
  1130.        INX  H 
  1131.        MOV  D,M 
  1132.        SHLD RANPNT
  1133.        POP  H 
  1134.        XCHG 
  1135.        PUSH B 
  1136.        CALL DIVIDE    ;RND(N)=MOD(M,N)+1 
  1137.        POP  B 
  1138.        POP  D 
  1139.        INX  H 
  1140.        RET
  1141. ;* 
  1142. ABS    CALL PARN      ;*** ABS(EXPR) *** 
  1143.        CALL CHKSGN    ;CHECK SIGN
  1144.        MOV  A,H       ;NOTE THAT -32768
  1145.        ORA  H         ;CANNOT CHANGE SIGN
  1146.        JM   QHOW      ;SO SAY: "HOW?"
  1147.        RET
  1148. SIZE   LHLD TXTUNF    ;*** SIZE ***
  1149.        PUSH D         ;GET THE NUMBER OF FREE
  1150.        XCHG           ;BYTES BETWEEN 'TXTUNF'
  1151. SIZEA  LXI  H,VARBGN  ;AND 'VARBGN'
  1152.        CALL SUBDE 
  1153.        POP  D 
  1154.        RET
  1155. ;*
  1156. ;*********************************************************
  1157. ;*
  1158. ;*   *** OUT *** INP *** WAIT *** POKE *** PEEK *** & USR
  1159. ;*
  1160. ;*  OUT I,J(,K,L)
  1161. ;*
  1162. ;*  OUTPUTS EXPRESSION 'J' TO PORT 'I', AND MAY BE REPEATED
  1163. ;*  AS IN DATA 'L' TO PORT 'K' AS MANY TIMES AS NEEDED
  1164. ;*  THIS COMMAND MODIFIES ;*  THIS COMMAND MODIFIES 
  1165. ;*  THIS COMMAND MODIFY'S A SMALL SECTION OF CODE LOCATED 
  1166. ;*  JUST ABOVE ADDRESS 2K
  1167. ;*
  1168. ;*  INP (I)
  1169. ;*
  1170. ;*  THIS FUNCTION RETURNS DATA READ FROM INPUT PORT 'I' AS
  1171. ;*  IT'S VALUE.
  1172. ;*  IT ALSO MODIFIES CODE JUST ABOVE 2K.
  1173. ;*
  1174. ;*  WAIT I,J,K
  1175. ;*
  1176. ;*  THIS COMMAND READS THE STATUS OF PORT 'I', EXCLUSIVE OR'S
  1177. ;*  THE RESULT WITH 'K' IF THERE IS ONE, OR IF NOT WITH 0, 
  1178. ;*  AND'S WITH 'J' AND RETURNS WHEN THE RESULT IS NONZERO.
  1179. ;*  ITS MODIFIED CODE IS ALSO ABOVE 2K.
  1180. ;*
  1181. ;*  POKE I,J(,K,L)
  1182. ;*
  1183. ;*  THIS COMMAND WORKS LIKE OUT EXCEPT THAT IT PUTS DATA 'J'
  1184. ;*  INTO MEMORY LOCATION 'I'.
  1185. ;*
  1186. ;*  PEEK (I)
  1187. ;*
  1188. ;*  THIS FUNCTION WORKS LIKE INP EXCEPT IT GETS IT'S VALUE
  1189. ;*  FROM MEMORY LOCATION 'I'.
  1190. ;*
  1191. ;*  USR (I(,J))
  1192. ;*
  1193. ;*  USR CALLS A MACHINE LANGUAGE SUBROUTINE AT LOCATION 'I'
  1194. ;*  IF THE OPTIONAL PARAMETER 'J' IS USED ITS VALUE IS PASSED
  1195. ;*  IN H&L.  THE VALUE OF THE FUNCTION SHOULD BE RETURNED IN H&L.
  1196. ;*
  1197. ;************************************************************
  1198. ;*
  1199. OUTCMD RST  3 
  1200.        MOV  A,L
  1201.        STA  OUTIO + 1
  1202.        RST  1
  1203.        DB   ','
  1204.        DB   2FH
  1205.        RST  3
  1206.        MOV  A,L
  1207.        CALL OUTIO
  1208.        RST  1
  1209.        DB   ','
  1210.        DB   03H
  1211.        JMP  OUTCMD 
  1212.        RST  6
  1213. WAITCM RST  3
  1214.        MOV  A,L
  1215.        STA  WAITIO + 1
  1216.        RST  1
  1217.        DB   ','
  1218.        DB   1BH
  1219.        RST  3
  1220.        PUSH H
  1221.        RST  1
  1222.        DB   ','
  1223.        DB   7H
  1224.        RST  3
  1225.        MOV  A,L
  1226.        POP  H
  1227.        MOV  H,A
  1228.        JMP  $ + 2
  1229.        MVI  H,0
  1230.        JMP  WAITIO
  1231. INP    CALL PARN
  1232.        MOV  A,L
  1233.        STA  INPIO + 1
  1234.        MVI  H,0
  1235.        JMP  INPIO
  1236.        JMP  QWHAT
  1237. POKE   RST  3
  1238.        PUSH H
  1239.        RST  1
  1240.        DB   ','
  1241.        DB   12H
  1242.        RST  3
  1243.        MOV  A,L
  1244.        POP  H
  1245.        MOV  M,A
  1246.        RST  1
  1247.        DB   ',',03H
  1248.        JMP  POKE
  1249.        RST 6
  1250. PEEK   CALL PARN
  1251.        MOV  L,M
  1252.        MVI  H,0
  1253.        RET
  1254.        JMP  QWHAT
  1255. USR    PUSH B
  1256.        RST  1
  1257.        DB   '(',28D    ;QWHAT
  1258.        RST  3          ;EXPR
  1259.        RST  1
  1260.        DB   ')',7      ;PASPARM
  1261.        PUSH D
  1262.        LXI  D,USRET
  1263.        PUSH D
  1264.        PUSH H
  1265.        RET             ;CALL USR ROUTINE
  1266. PASPRM RST  1
  1267.        DB   ',',14D
  1268.        PUSH H
  1269.        RST  3
  1270.        RST  1
  1271.        DB   ')',9
  1272.        POP  B
  1273.        PUSH D
  1274.        LXI  D,USRET
  1275.        PUSH D
  1276.        PUSH B
  1277.        RET             ;CALL USR ROUTINE
  1278. USRET  POP  D
  1279.        POP  B
  1280.        RET
  1281.        JMP  QWHAT
  1282. ;*
  1283. ;**************************************************************
  1284. ;* 
  1285. ;* *** DIVIDE *** SUBDE *** CHKSGN *** CHGSGN *** & CKHLDE *** 
  1286. ;* 
  1287. ;* 'DIVIDE' DIVIDES HL BY DE, RESULT IN BC, REMAINDER IN HL
  1288. ;* 
  1289. ;* 'SUBDE' SUBTRACTS DE FROM HL
  1290. ;* 
  1291. ;* 'CHKSGN' CHECKS SIGN OF HL.  IFF +, NO CHANGE.  IFF -, CHANGE 
  1292. ;* SIGN AND FLIP SIGN OF B.
  1293. ;* 
  1294. ;* 'CHGSGN' CHNGES SIGN OF HL AND B UNCONDITIONALLY. 
  1295. ;* 
  1296. ;* 'CKHLE' CHECKS SIGN OF HL AND DE.  IFF DIFFERENT, HL AND DE 
  1297. ;* ARE INTERCHANGED.  IFF SAME SIGN, NOT INTERCHANGED.  EITHER
  1298. ;* CASE, HL DE ARE THEN COMPARED TO SET THE FLAGS. 
  1299. ;* 
  1300. DIVIDE PUSH H         ;*** DIVIDE ***
  1301.        MOV  L,H       ;DIVIDE H BY DE
  1302.        MVI  H,0 
  1303.        CALL DV1 
  1304.        MOV  B,C       ;SAVE RESULT IN B
  1305.        MOV  A,L       ;(REMAINDER+L)/DE
  1306.        POP  H 
  1307.        MOV  H,A 
  1308. DV1    MVI  C,377Q    ;RESULT IN C 
  1309. DV2    INR  C         ;DUMB ROUTINE
  1310.        CALL SUBDE     ;DIVIDE BY SUBTRACT
  1311.        JNC  DV2       ;AND COUNT 
  1312.        DAD  D 
  1313.        RET
  1314. ;* 
  1315. SUBDE  MOV  A,L       ;*** SUBDE *** 
  1316.        SUB  E         ;SUBTRACT DE FROM
  1317.        MOV  L,A       ;HL
  1318.        MOV  A,H 
  1319.        SBB  D 
  1320.        MOV  H,A 
  1321.        RET
  1322. ;* 
  1323. CHKSGN MOV  A,H       ;*** CHKSGN ***
  1324.        ORA  A         ;CHECK SIGN OF HL
  1325.        RP             ;IFF -, CHANGE SIGN 
  1326. ;* 
  1327. CHGSGN MOV  A,H       ;*** CHGSGN ***
  1328.        CMA            ;CHANGE SIGN OF HL 
  1329.        MOV  H,A 
  1330.        MOV  A,L 
  1331.        CMA
  1332.        MOV  L,A 
  1333.        INX  H 
  1334.        MOV  A,B       ;AND ALSO FLIP B 
  1335.        XRI  200Q
  1336.        MOV  B,A 
  1337.        RET
  1338. ;* 
  1339. CKHLDE MOV  A,H 
  1340.        XRA  D         ;SAME SIGN?
  1341.        JP   CK1       ;YES, COMPARE
  1342.        XCHG           ;NO, XCH AND COMP
  1343. CK1    RST  4 
  1344.        RET
  1345. ;* 
  1346. ;**************************************************************
  1347. ;* 
  1348. ;* *** SETVAL *** FIN *** ENDCHK *** & ERROR (& FRIENDS) *** 
  1349. ;* 
  1350. ;* "SETVAL" EXPECTS A VARIABLE, FOLLOWED BY AN EQUAL SIGN AND
  1351. ;* THEN AN EXPR.  IT EVALUATES THE EXPR. AND SET THE VARIABLE
  1352. ;* TO THAT VALUE.
  1353. ;* 
  1354. ;* "FIN" CHECKS THE END OF A COMMAND.  IFF IT ENDED WITH ";", 
  1355. ;* EXECUTION CONTINUES.  IFF IT ENDED WITH A CR, IT FINDS THE 
  1356. ;* NEXT LINE AND CONTINUE FROM THERE.
  1357. ;* 
  1358. ;* "ENDCHK" CHECKS IFF A COMMAND IS ENDED WITH CR.  THIS IS 
  1359. ;* REQUIRED IN CERTAIN COMMANDS. (GOTO, RETURN, AND STOP ETC.) 
  1360. ;* 
  1361. ;* "ERROR" PRINTS THE STRING POINTED BY DE (AND ENDS WITH CR). 
  1362. ;* IT THEN PRINTS THE LINE POINTED BY 'CURRNT' WITH A "?"
  1363. ;* INSERTED AT WHERE THE OLD TEXT POINTER (SHOULD BE ON TOP
  1364. ;* O THE STACK) POINTS TO.  EXECUTION OF TB IS STOPPED
  1365. ;* AND TBI IS RESTARTED.  HOWEVER, IFF 'CURRNT' -> ZERO 
  1366. ;* (INDICATING A DIRECT COMMAND), THE DIRECT COMMAND IS NOT
  1367. ;*  PRINTED.  AND IFF 'CURRNT' -> NEGATIVE # (INDICATING 'INPUT'
  1368. ;* COMMAND, THE INPUT LINE IS NOT PRINTED AND EXECUTION IS 
  1369. ;* NOT TERMINATED BUT CONTINUED AT 'INPERR'. 
  1370. ;* 
  1371. ;* RELATED TO 'ERROR' ARE THE FOLLOWING: 
  1372. ;* 'QWHAT' SAVES TEXT POINTER IN STACK AND GET MESSAGE "WHAT?" 
  1373. ;* 'AWHAT' JUST GET MESSAGE "WHAT?" AND JUMP TO 'ERROR'. 
  1374. ;* 'QSORRY' AND 'ASORRY' DO SAME KIND OF THING.
  1375. ;* 'QHOW' AND 'AHOW' IN THE ZERO PAGE SECTION ALSO DO THIS 
  1376. ;* 
  1377. SETVAL RST  7         ;*** SETVAL ***
  1378.        JC   QWHAT     ;"WHAT?" NO VARIABLE 
  1379.        PUSH H         ;SAVE ADDRESS OF VAR.
  1380.        RST  1         ;PASS "=" SIGN 
  1381.        DB   '=' 
  1382.        DB   10Q 
  1383.        RST  3         ;EVALUATE EXPR.
  1384.        MOV  B,H       ;VALUE IN BC NOW 
  1385.        MOV  C,L 
  1386.        POP  H         ;GET ADDRESS 
  1387.        MOV  M,C       ;SAVE VALUE
  1388.        INX  H 
  1389.        MOV  M,B 
  1390.        RET
  1391. SV1    JMP  QWHAT     ;NO "=" SIGN 
  1392. ;* 
  1393. FIN    RST  1         ;*** FIN *** 
  1394.        DB   73Q 
  1395.        DB   4Q 
  1396.        POP  PSW       ;";", PURGE RET ADDR.
  1397.        JMP  RUNSML    ;CONTINUE SAME LINE
  1398. FI1    RST  1         ;NOT ";", IS IT CR?
  1399.        DB   0DH
  1400.        DB   4Q 
  1401.        POP  PSW       ;YES, PURGE RET ADDR.
  1402.        JMP  RUNNXL    ;RUN NEXT LINE 
  1403. FI2    RET            ;ELSE RETURN TO CALLER 
  1404. ;* 
  1405. ENDCHK RST  5         ;*** ENDCHK ***
  1406.        CPI  0DH       ;END WITH CR?
  1407.        RZ             ;OK, ELSE SAY: "WHAT?" 
  1408. ;* 
  1409. QWHAT  PUSH D         ;*** QWHAT *** 
  1410. AWHAT  LXI  D,WHAT    ;*** AWHAT *** 
  1411. ERROR  SUB  A         ;*** ERROR *** 
  1412.        CALL PRTSTG    ;PRINT 'WHAT?', 'HOW?' 
  1413.        POP  D         ;OR 'SORRY'
  1414.        LDAX D         ;SAVE THE CHARACTER
  1415.        PUSH PSW       ;AT WHERE OLD DE ->
  1416.        SUB  A         ;AND PUT A 0 THERE 
  1417.        STAX D 
  1418.        LHLD CURRNT    ;GET CURRENT LINE #
  1419.        PUSH H 
  1420.        MOV  A,M       ;CHECK THE VALUE 
  1421.        INX  H 
  1422.        ORA  M 
  1423.        POP  D 
  1424.        JZ   RSTART    ;IFF ZERO, JUST RERSTART
  1425.        MOV  A,M       ;IFF NEGATIVE,
  1426.        ORA  A 
  1427.        JM   INPERR    ;REDO INPUT
  1428.        CALL PRTLN     ;ELSE PRINT THE LINE 
  1429.        DCX  D         ;UPTO WHERE THE 0 IS 
  1430.        POP  PSW       ;RESTORE THE CHARACTER 
  1431.        STAX D 
  1432.        MVI  A,77Q     ;PRINTt A "?" 
  1433.        RST  2 
  1434.        SUB  A         ;AND THE REST OF THE 
  1435.        CALL PRTSTG    ;LINE
  1436.        JMP  RSTART
  1437. QSORRY PUSH D         ;*** QSORRY ***
  1438. ASORRY LXI  D,SORRY   ;*** ASORRY ***
  1439.        JMP  ERROR 
  1440. ;* 
  1441. ;**************************************************************
  1442. ;* 
  1443. ;* *** GETLN *** FNDLN (& FRIENDS) *** 
  1444. ;* 
  1445. ;* 'GETLN' READS A INPUT LINE INTO 'BUFFER'.  IT FIRST PROMPT
  1446. ;* THE CHARACTER IN A (GIVEN BY THE CALLER), THEN IT FILLS THE 
  1447. ;* THE BUFFER AND ECHOS.  IT IGNORES LF'S AND NULLS, BUT STILL 
  1448. ;* ECHOS THEM BACK.  RUB-OUT IS USED TO CAUSE IT TO DELETE 
  1449. ;* THE LAST CHARATER (IFF THERE IS ONE), AND ALT-MOD IS USED TO 
  1450. ;* CAUSE IT TO DELETE THE WHOLE LINE AND START IT ALL OVER.
  1451. ;* 0DHSIGNALS THE END OF A LINE, AND CAUE 'GETLN' TO RETURN.
  1452. ;* 
  1453. ;* 'FNDLN' FINDS A LINE WITH A GIVEN LINE # (IN HL) IN THE 
  1454. ;* TEXT SAVE AREA.  DE IS USED AS THE TEXT POINTER.  IFF THE
  1455. ;* LINE IS FOUND, DE WILL POINT TO THE BEGINNING OF THAT LINE
  1456. ;* (I.E., THE LOW BYTE OF THE LINE #), AND FLAGS ARE NC & Z. 
  1457. ;* IFF THAT LINE IS NOT THERE AND A LINE WITH A HIGHER LINE # 
  1458. ;* IS FOUND, DE POINTS TO THERE AND FLAGS ARE NC & NZ.  IFF 
  1459. ;* WE REACHED THE END OF TEXT SAVE ARE AND CANNOT FIND THE 
  1460. ;* LINE, FLAGS ARE C & NZ. 
  1461. ;* 'FNDLN' WILL INITIALIZE DE TO THE BEGINNING OF THE TEXT SAVE
  1462. ;* AREA TO START THE SEARCH.  SOME OTHER ENTRIES OF THIS 
  1463. ;* ROUTINE WILL NOT INITIALIZE DE AND DO THE SEARCH. 
  1464. ;* 'FNDLNP' WILL START WITH DE AND SEARCH FOR THE LINE #.
  1465. ;* 'FNDNXT' WILL BUMP DE BY 2, FIND A 0DHAND THEN START SEARCH.
  1466. ;* 'FNDSKP' USE DE TO FIND A CR, AND THEN STRART SEARCH. 
  1467. ;* 
  1468. GETLN  RST  2         ;*** GETLN *** 
  1469.        LXI  D,BUFFER  ;PROMPT AND INIT
  1470. GL1    CALL CHKIO     ;CHECK KEYBOARD
  1471.        JZ   GL1       ;NO INPUT, WAIT
  1472.        CPI  177Q      ;DELETE LST CHARACTER?
  1473.        JZ   GL3       ;YES 
  1474.        CPI  12Q       ;IGNORE LF 
  1475.        JZ   GL1 
  1476.        ORA  A         ;IGNORE NULL 
  1477.        JZ   GL1 
  1478.        CPI  134Q      ;DELETE THE WHOLE LINE?
  1479.        JZ   GL4       ;YES 
  1480.        STAX D         ;ELSE, SAVE INPUT
  1481.        INX  D         ;AND BUMP POINTER
  1482.        CPI  15Q       ;WAS IT CR?
  1483.        JNZ  GL2       ;NO
  1484.        MVI  A,12Q     ;YES, GET LINE FEED
  1485.        RST  2         ;CALL OUTC AND LINE FEED
  1486.        RET            ;WE'VE GOT A LINE
  1487. GL2    MOV  A,E       ;MORE FREE ROOM?
  1488.        CPI  BUFEND AND 0FFH
  1489.        JNZ  GL1       ;YES, GET NEXT INPUT 
  1490. GL3    MOV  A,E       ;DELETE LAST CHARACTER 
  1491.        CPI  BUFFER AND 0FFH    ;BUT DO WE HAVE ANY? 
  1492.        JZ   GL4       ;NO, REDO WHOLE LINE 
  1493.        DCX  D         ;YES, BACKUP POINTER 
  1494.        MVI  A,'_'     ;AND ECHO A BACK-SPACE 
  1495.        RST  2 
  1496.        JMP  GL1       ;GO GET NEXT INPUT 
  1497. GL4    CALL CRLF      ;REDO ENTIRE LINE
  1498.        MVI  A,136Q    ;CR, LF AND UP-ARROW 
  1499.        JMP  GETLN 
  1500. ;* 
  1501. FNDLN  MOV  A,H       ;*** FNDLN *** 
  1502.        ORA  A         ;CHECK SIGN OF HL
  1503.        JM   QHOW      ;IT CANNT BE -
  1504.        LXI  D,TXTBGN  ;INIT. TEXT POINTER
  1505. ;* 
  1506. FNDLNP EQU  $         ;*** FNDLNP ***
  1507. FL1    PUSH H         ;SAVE LINE # 
  1508.        LHLD TXTUNF    ;CHECK IFF WE PASSED END
  1509.        DCX  H 
  1510.        RST  4 
  1511.        POP  H         ;GET LINE # BACK 
  1512.        RC             ;C,NZ PASSED END 
  1513.        LDAX D         ;WE DID NOT, GET BYTE 1
  1514.        SUB  L         ;IS THIS THE LINE? 
  1515.        MOV  B,A       ;COMPARE LOW ORDER 
  1516.        INX  D 
  1517.        LDAX D         ;GET BYTE 2
  1518.        SBB  H         ;COMPARE HIGH ORDER
  1519.        JC   FL2       ;NO, NOT THERE YET 
  1520.        DCX  D         ;ELSE WE EITHER FOUND
  1521.        ORA  B         ;IT, OR IT IS NOT THERE
  1522.        RET            ;NC,Z:FOUND; NC,NZ:NO
  1523. ;* 
  1524. FNDNXT EQU  $         ;*** FNDNXT ***
  1525.        INX  D         ;FIND NEXT LINE
  1526. FL2    INX  D         ;JUST PASSED BYTE 1 & 2
  1527. ;* 
  1528. FNDSKP LDAX D         ;*** FNDSKP ***
  1529.        CPI  0DH       ;TRY TO FIND 0DH
  1530.        JNZ  FL2       ;KEEP LOOKING
  1531.        INX  D         ;FOUND CR, SKIP OVER 
  1532.        JMP  FL1       ;CHECK IFF END OF TEXT
  1533. ;* 
  1534. ;*************************************************************
  1535. ;* 
  1536. ;* *** PRTSTG *** QTSTG *** PRTNUM *** & PRTLN *** 
  1537. ;* 
  1538. ;* 'PRTSTG' PRINTS A STRING POINTED BY DE.  IT STOPS PRINTING
  1539. ;* AND RETURNS TO CALâ• ER WHEN EITHER A 0DHIS PRINTED OR WHEN 
  1540. ;* THE NEXT BYTE IS THE SAME AS WHAT WAS IN A (GIVEN BY THE
  1541. ;* CALLER).  OLD A IS STORED IN B, OLD B IS LOST.
  1542. ;* 
  1543. ;* 'QTSTG' LOOKS FOR A BACK-ARROW, SINGLE QUOTE, OR DOUBLE 
  1544. ;* QUOTE.  IFF NONE OF THESE, RETURN TO CALLER.  IFF BACK-ARROW, 
  1545. ;* OUTPUT A 0DHWITHOUT A LF.  IFF SINGLE OR DOUBLE QUOTE, PRINT 
  1546. ;* THE STRING IN THE QUOTE AND DEMANDS A MATCHING UNQUOTE. 
  1547. ;* AFTER THE PRINTING THE NEXT 3 BYTES OF THE CALLER IS SKIPPED
  1548. ;* OVER (USUALLY A JUMP INSTRUCTION).
  1549. ;* 
  1550. ;* 'PRTNUM' PRINTS THE NUMBER IN HL.  LEADING BLANKS ARE ADDED 
  1551. ;* IFF NEEDED TO PAD THE NUMBER OF SPACES TO THE NUMBER IN C. 
  1552. ;* HOWEVER, IFF THE NUMBER OF DIGITS IS LARGER THAN THE # IN
  1553. ;* C, ALL DIGITS ARE PRINTED ANYWAY.  NEGATIVE SIGN IS ALSO
  1554. ;* PRINTED AND COUNTED IN, POSITIVE SIGN IS NOT. 
  1555. ;* 
  1556. ;* 'PRTLN' PRINSrA SAVED TEXT LINE WITH LINE # AND ALL. 
  1557. ;* 
  1558. PRTSTG MOV  B,A       ;*** PRTSTG ***
  1559. PS1    LDAX D         ;GET A CHARACTERr 
  1560.        INX  D         ;BUMP POINTER
  1561.        CMP  B         ;SAME AS OLD A?
  1562.        RZ             ;YES, RETURN 
  1563.        RST  2         ;ELSE PRINT IT 
  1564.        CPI  0DH       ;WAS IT A CR?
  1565.        JNZ  PS1       ;NO, NEXT
  1566.        RET            ;YES, RETURN 
  1567. ;* 
  1568. QTSTG  RST  1         ;*** QTSTG *** 
  1569.        DB   '"' 
  1570.        DB   17Q 
  1571.        MVI  A,42Q     ;IT IS A " 
  1572. QT1    CALL PRTSTG    ;PRINT UNTIL ANOTHER 
  1573.        CPI  0DH       ;WAS LAST ONE A CR?
  1574.        POP  H         ;RETURN ADDRESS
  1575.        JZ   RUNNXL    ;WAS CR, RUN NEXT LINE 
  1576. QT2    INX  H         ;SKIP 3 BYTES ON RETURN
  1577.        INX  H 
  1578.        INX  H 
  1579.        PCHL           ;RETURN
  1580. QT3    RST  1         ;IS IT A ' ? 
  1581.        DB   47Q 
  1582.        DB   5Q
  1583.        MVI  A,47Q     ;YES, DO SAME
  1584.        JMP  QT1       ;AS IN " 
  1585. QT4    RST  1         ;IS IT BACK-ARROW? 
  1586.        DB   137Q
  1587.        DB   10Q 
  1588.        MVI  A,215Q    ;YES, 0DHWITHOUT LF!!
  1589.        RST  2         ;DO IT TWICE TO GIVE 
  1590.        RST  2         ;TTY ENOUGH TIME 
  1591.        POP  H         ;RETURN ADDRESS
  1592.        JMP  QT2 
  1593. QT5    RET            ;NONE OF ABOVE 
  1594. ;* 
  1595. PRTNUM PUSH D         ;*** PRTNUM ***
  1596.        LXI  D,12Q     ;DECIMAL 
  1597.        PUSH D         ;SAVE AS A FLAG
  1598.        MOV  B,D       ;B=SIGN
  1599.        DCR  C         ;C=SPACES
  1600.        CALL CHKSGN    ;CHECK SIGN
  1601.        JP   PN1       ;NO SIGN 
  1602.        MVI  B,55Q     ;B=SIGN
  1603.        DCR  C         ;'-' TAKES SPACE 
  1604. PN1    PUSH B         ;SAVE SIGN & SPACE 
  1605. PN2    CALL DIVIDE    ;DEVIDE HL BY 10 
  1606.        MOV  A,B       ;RESULT 0? 
  1607.        ORA  C 
  1608.        JZ   PN3       ;YES, WE GOT ALL 
  1609.        XTHL           ;NO, SAVE REMAINDER
  1610.        DCR  L         ;AND COUNT SPACE 
  1611.        PUSH H         ;HL IS OLD BC
  1612.        MOV  H,B       ;MOVE RESULT TO BC 
  1613.        MOV  L,C 
  1614.        JMP  PN2       ;AND DIVIDE BY 10
  1615. PN3    POP  B         ;WE GOT ALL DIGITS IN
  1616. PN4    DCR  C         ;THE STACK 
  1617.        MOV  A,C       ;LOOK AT SPACE COUNT 
  1618.        ORA  A 
  1619.        JM   PN5       ;NO LEADING BLANKS 
  1620.        MVI  A,40Q     ;LEADING BLANKS
  1621.        RST  2 
  1622.        JMP  PN4       ;MORE? 
  1623. PN5    MOV  A,B       ;PRINT SIGN
  1624.        RST  2         ;MAYBE - OR NULL 
  1625.        MOV  E,L       ;LAST REMAINDER IN E 
  1626. PN6    MOV  A,E       ;CHECK DIGIT IN E
  1627.        CPI  12Q       ;10 IS FLAG FOR NO MORE
  1628.        POP  D 
  1629.        RZ             ;IFF SO, RETURN 
  1630.        ADI  60Q        ;ELSE CONVERT TO ASCII
  1631.        RST  2         ;AND PRINT THE DIGIT 
  1632.        JMP  PN6       ;GO BACK FOR MORE
  1633. ;* 
  1634. PRTLN  LDAX D         ;*** PRTLN *** 
  1635.        MOV  L,A       ;LOW ORDER LINE #
  1636.        INX  D 
  1637.        LDAX D         ;HIGH ORDER
  1638.        MOV  H,A 
  1639.        INX  D 
  1640.        MVI  C,4Q      ;PRINT 4 DIGIT LINE #
  1641.        CALL PRTNUM
  1642.        MVI  A,40Q     ;FOLLOWED BY A BLANK 
  1643.        RST  2 
  1644.        SUB  A         ;AND THEN THE TEXT 
  1645.        CALL PRTSTG
  1646.        RET
  1647. ;* 
  1648. ;**************************************************************
  1649. ;* 
  1650. ;* *** MVUP *** MVDOWN *** POPA *** & PUSHA ***
  1651. ;* 
  1652. ;* 'MVUP' MOVES A BLOCK UP FROM HERE DE-> TO WHERE BC-> UNTIL 
  1653. ;* DE = HL 
  1654. ;* 
  1655. ;* 'MVDOWN' MOVES A BLOCK DOWN FROM WHERE DE-> TO WHERE HL-> 
  1656. ;* UNTIL DE = BC 
  1657. ;* 
  1658. ;* 'POPA' RESTORES THE 'FOR' LOOP VARIABLE SAVE AREA FROM THE
  1659. ;* STACK 
  1660. ;* 
  1661. ;* 'PUSHA' STACKS THE 'FOR' LOOP VARIABLE SAVE AREA INTO THE 
  1662. ;* STACK 
  1663. ;* 
  1664. MVUP   RST  4         ;*** MVUP ***
  1665.        RZ             ;DE = HL, RETURN 
  1666.        LDAX D         ;GET ONE BYTE
  1667.        STAX B         ;MOVE IT 
  1668.        INX  D         ;INCREASE BOTH POINTERS
  1669.        INX  B 
  1670.        JMP  MVUP      ;UNTIL DONE
  1671. ;* 
  1672. MVDOWN MOV  A,B       ;*** MVDOWN ***
  1673.        SUB  D         ;TEST IFF DE = BC 
  1674.        JNZ  MD1       ;NO, GO MOVE 
  1675.        MOV  A,C       ;MAYBE, OTHER BYTE?
  1676.        SUB  E 
  1677.        RZ             ;YES, RETURN 
  1678. MD1    DCX  D         ;ELSE MOVE A BYTE
  1679.        DCX  H         ;BUT FIRST DECREASE
  1680.        LDAX D         ;BOTH POINTERS AND 
  1681.        MOV  M,A       ;THEN DO IT
  1682.        JMP  MVDOWN    ;LOOP BACK 
  1683. ;* 
  1684. POPA   POP  B         ;BC = RETURN ADDR. 
  1685.        POP  H         ;RESTORE LOPVAR, BUT 
  1686.        SHLD LOPVAR    ;=0 MEANS NO MORE
  1687.        MOV  A,H 
  1688.        ORA  L 
  1689.        JZ   PP1       ;YEP, GO RETURN
  1690.        POP  H         ;NOP, RESTORE OTHERS 
  1691.        SHLD LOPINC
  1692.        POP  H 
  1693.        SHLD LOPLMT
  1694.        POP  H 
  1695.        SHLD LOPLN 
  1696.        POP  H 
  1697.        SHLD LOPPT 
  1698. PP1    PUSH B         ;BC = RETURN ADDR. 
  1699.        RET
  1700. ;* 
  1701. PUSHA  LXI  H,STKLMT  ;*** PUSHA *** 
  1702.        CALL CHGSGN
  1703.        POP  B         ;BC=RETURN ADDRESS 
  1704.        DAD  SP        ;IS STACK NEAR THE TOP?
  1705.        JNC  QSORRY    ;YES, SORRY FOR THAT.
  1706.        LHLD LOPVAR    ;ELSE SAVE LOOP VAR.S
  1707.        MOV  A,H       ;BUT IFF LOPVAR IS 0
  1708.        ORA  L         ;THAT WILL BE ALL
  1709.        JZ   PU1 
  1710.        LHLD LOPPT     ;ELSE, MORE TO SAVE
  1711.        PUSH H 
  1712.        LHLD LOPLN 
  1713.        PUSH H 
  1714.        LHLD LOPLMT
  1715.        PUSH H 
  1716.        LHLD LOPINC
  1717.        PUSH H 
  1718.        LHLD LOPVAR
  1719. PU1    PUSH H 
  1720.        PUSH B         ;BC = RETURN ADDR. 
  1721.        RET
  1722. ;* 
  1723. ;**************************************************************
  1724. ;* 
  1725. ;* *** OUTC *** & CHKIO ****!
  1726. ;* THESE ARE THE ONLY I/O ROUTINES IN TBI. 
  1727. ;* 'OUTC' IS CONTROLLED BY A SOFTWARE SWITCH 'OCSW'.  IFF OCSW=0
  1728. ;* 'OUTC' WILL JUST RETURN TO THE CALLER.  IFF OCSW IS NOT 0, 
  1729. ;* IT WILL OUTPUT THE BYTE IN A.  IFF THAT IS A CR, A LF IS ALSO
  1730. ;* SEND OUT.  ONLY THE FLAGS MAY BE CHANGED AT RETURN, ALL REG.
  1731. ;* ARE RESTORED. 
  1732. ;* 
  1733. ;* 'CHKIO' CHECKS THE INPUT.  IFF NO INPUT, IT WILL RETURN TO 
  1734. ;* THE CALLER WITH THE Z FLAG SET.  IFF THERE IS INPUT, Z FLAG
  1735. ;* IS CLEARED AND THE INPUT BYTE IS IN A.  HOWERER, IFF THE 
  1736. ;* INPUT IS A CONTROL-O, THE 'OCSW' SWITCH IS COMPLIMENTED, AND
  1737. ;* Z FLAG IS RETURNED.  IFF A CONTROL-C IS READ, 'CHKIO' WILL 
  1738. ;* RESTART TBI AND DO NOT RETURN TO THE CALLER.
  1739. ;* 
  1740. ;*                 OUTC   PUSH AF        THIS IS AT LOC. 10
  1741. ;*                        LD   A,OCSW    CHECK SOFTWARE SWITCH 
  1742. ;*                        IOR  A 
  1743. OC2    JNZ  OC3       ;IT IS ON
  1744.        POP  PSW       ;IT IS OFF 
  1745.        RET            ;RESTORE AF AND RETURN 
  1746. OC3    POP  A         ;GET OLD A BACK
  1747.        PUSH B         ;SAVE B ON STACK
  1748.        PUSH D         ;AND D
  1749.        PUSH H         ;AND H TOO
  1750.        STA  OUTCAR    ;SAVE CHARACTER
  1751.        MOV  E,A       ;PUT CHAR. IN E FOR CPM
  1752.        MVI  C,2       ;GET CONOUT COMMAND
  1753.        CALL CPM       ;CALL CPM AND DO IT
  1754.        LDA  OUTCAR    ;GET CHAR. BACK
  1755.        CPI  0DH       ;WAS IT A 'CR'?
  1756.        JNZ  DONE      ;NO, DONE
  1757.        MVI  E,0AH     ;GET LINEFEED
  1758.        MVI  C,2       ;AND CONOUT AGAIN
  1759.        CALL CPM       ;CALL CPM
  1760. DONE   LDA  OUTCAR    ;GET CHARACTER BACK
  1761. IDONE  POP  H         ;GET H BACK
  1762.        POP  D         ;AND D
  1763.        POP  B         ;AND B TOO
  1764.        RET            ;DONE AT LAST
  1765. CHKIO  PUSH B         ;SAVE B ON STACK
  1766.        PUSH D         ;AND D
  1767.        PUSH H         ;THEN H
  1768.        MVI  C,11      ;GET CONSTAT WORD
  1769.        CALL CPM       ;CALL THE BDOS
  1770.        ORA  A         ;SET FLAGS
  1771.        JNZ  CI1       ;IF READY GET CHARACTER
  1772.        JMP  IDONE     ;RESTORE AND RETURN
  1773. CI1    MVI  C,1       ;GET CONIN WORD
  1774.        CALL CPM       ;CALL THE BDOS
  1775.        CPI  0FH       ;IS IT CONTROL-O?
  1776.        JNZ  CI2       ;NO, MORE CHECKING
  1777.        LDA  OCSW      ;CONTROL-O  FLIP OCSW
  1778.        CMA            ;ON TO OFF, OFF TO ON
  1779.        STA  OCSW      ;AND PUT IT BACK
  1780.        JMP  CHKIO     ;AND GET ANOTHER CHARACTER
  1781. CI2    CPI  3         ;IS IT CONTROL-C?
  1782.        JNZ  IDONE     ;RETURN AND RESTORE IF NOT
  1783.        JMP  RSTART    ;YES, RESTART TBI
  1784. LSTROM EQU  $         ;ALL ABOVE CAN BE ROM
  1785. OUTIO  OUT  0FFH
  1786.        RET
  1787. WAITIO IN   0FFH
  1788.        XRA  H
  1789.        ANA  L
  1790.        JZ   WAITIO
  1791.        RST  6
  1792. INPIO  IN   0FFH
  1793.        MOV  L,A
  1794.        RET
  1795. OUTCAR DB   0         ;OUTPUT CHAR. STORAGE
  1796. OCSW   DB   0FFH      ;SWITCH FOR OUTPUT
  1797. CURRNT DW   0         ;POINTS TO CURRENT LINE
  1798. STKGOS DW   0         ;SAVES SP IN 'GOSUB'
  1799. VARNXT DW   0         ;TEMPORARY STORAGE
  1800. STKINP DW   0         ;SAVES SP IN 'INPUT'
  1801. LOPVAR DW   0         ;'FOR' LOOP SAVE AREA
  1802. LOPINC DW   0         ;INCREMENT
  1803. LOPLMT DW   0         ;LIMIT
  1804. LOPLN  DW   0         ;LINE NUMBER
  1805. LOPPT  DW   0         ;TEXT POINTER
  1806. RANPNT DW   START     ;RANDOM NUMBER POINTER
  1807. TXTUNF DW   TXTBGN    ;->UNFILLED TEXT AREA
  1808. TXTBGN DS   1         ;TEXT SAVE AREA BEGINS 
  1809. MSG1   DB   7FH,7FH,7FH,'SHERRY BROTHERS TINY BASIC VER. 3.1',0DH 
  1810. INIT   MVI  A,0FFH
  1811.        STA  OCSW      ;TURN ON OUTPUT SWITCH 
  1812.        MVI  A,0CH     ;GET FORM FEED 
  1813.        RST  2         ;SEND TO CRT 
  1814. PATLOP SUB  A         ;CLEAR ACCUMULATOR
  1815.        LXI  D,MSG1    ;GET INIT MESSAGE
  1816.        CALL PRTSTG    ;SEND IT
  1817. LSTRAM LDA  7         ;GET FBASE FOR TOP
  1818.        STA  RSTART+2
  1819.        DCR  A         ;DECREMENT FOR OTHER POINTERS
  1820.        STA  SS1A+2    ;AND FIX THEM TOO
  1821.        STA  TV1A+2
  1822.        STA  ST3A+2
  1823.        STA  ST4A+2
  1824.        STA  IP3A+2
  1825.        STA  SIZEA+2
  1826.        STA  GETLN+3
  1827.        STA  PUSHA+2
  1828.        LXI  H,ST1     ;GET NEW START JUMP
  1829.        SHLD START+1   ;AND FIX IT
  1830.        JMP  ST1
  1831. ;    RESTART TABLE
  1832.     ORG    0A50H
  1833. RSTBL:
  1834.        XTHL           ;*** TSTC OR RST 1 *** 
  1835.        RST  5         ;IGNORE BLANKS AND 
  1836.        CMP  M         ;TEST CHARACTER
  1837.        JMP  TC1       ;REST OF THIS IS AT TC1
  1838. ;* 
  1839. CRLF:    EQU    0EH    ;EXECUTE TIME LOCATION OF THIS INSTRUCTION.
  1840.     MVI  A,0DH     ;*** CRLF ***
  1841. ;* 
  1842.        PUSH PSW       ;*** OUTC OR RST 2 *** 
  1843.        LDA  OCSW      ;PRINT CHARACTER ONLY
  1844.        ORA  A         ;IFF OCSW SWITCH IS ON
  1845.        JMP  OC2       ;REST OF THIS IS AT OC2
  1846. ;* 
  1847.        CALL EXPR2     ;*** EXPR OR RST 3 *** 
  1848.        PUSH H         ;EVALUATE AN EXPRESION 
  1849.        JMP  EXPR1     ;REST OF IT IS AT EXPR1
  1850.        DB   'W' 
  1851. ;* 
  1852.        MOV  A,H       ;*** COMP OR RST 4 *** 
  1853.        CMP  D         ;COMPARE HL WITH DE
  1854.        RNZ            ;RETURN CORRECT C AND
  1855.        MOV  A,L       ;Z FLAGS 
  1856.        CMP  E         ;BUT OLD A IS LOST 
  1857.        RET
  1858.        DB   'AN'
  1859. ;* 
  1860. SS1:    EQU    28H    ;EXECUTE TIME LOCATION OF THIS INSTRUCTION.
  1861.     LDAX D         ;*** IGNBLK/RST 5 ***
  1862.        CPI  40Q       ;IGNORE BLANKS 
  1863.        RNZ            ;IN TEXT (WHERE DE->)
  1864.        INX  D         ;AND RETURN THE FIRST
  1865.        JMP  SS1       ;NON-BLANK CHAR. IN A
  1866. ;* 
  1867.        POP  PSW       ;*** FINISH/RST 6 ***
  1868.        CALL FIN       ;CHECK END OF COMMAND
  1869.        JMP  QWHAT     ;PRINT "WHAT?" IFF WRONG
  1870.        DB   'G' 
  1871. ;* 
  1872.        RST  5         ;*** TSTV OR RST 7 *** 
  1873.        SUI  100Q      ;TEST VARIABLES
  1874.        RC             ;C:NOT A VARIABLE
  1875.        JMP  TSTV1     ;JUMP AROUND RESERVED AREA
  1876. ; ROUTINE TO COPY RESTART TABLE INTO LOW MEMORY
  1877. RST1:    EQU    8    ;LOCATION FIRST REATART ROUTINE
  1878.  
  1879. EOT:    EQU    40H    ;LAST LOC TO BE FILLED
  1880.  
  1881.     ORG    0AA0H
  1882. NINIT:    LXI    H,RST1        ;POINT TO BEGINNING OF MODEL TABLE
  1883.     LXI    D,RSTBL
  1884. NXT:    LDAX    D
  1885.     MOV    M,A
  1886.     INX    H
  1887.     INX    D
  1888.     MVI    A,EOT
  1889.     CMP    L
  1890.     JNZ    NXT
  1891.     LXI    H,INIT
  1892.     SHLD    START+1
  1893.     JMP    START
  1894.        ORG  0F00H
  1895. TXTEND EQU  $         ;TEXT SAVE AREA ENDS 
  1896. VARBGN DS   2*27      ;VARIABLE @(0)
  1897.        DS   1         ;EXTRA BYTE FOR BUFFER
  1898. BUFFER DS   80        ;INPUT BUFFER
  1899. BUFEND EQU  $         ;BUFFER ENDS
  1900.        DS   40        ;EXTRA BYTES FOR STACK
  1901. STKLMT EQU  $         ;TOP LIMIT FOR STACK
  1902.        ORG  2000H
  1903. STACK  EQU  $         ;STACK STARTS HERE
  1904.        END
  1905.