home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / SIMTEL / CPMUG / CPMUG024.ARK / TAPELIB.MAC < prev    next >
Text File  |  1984-04-29  |  38KB  |  1,538 lines

  1. ;            -- TAPELIB --
  2. ;
  3. ;                    BY:  S. J. SINGER
  4. ;                        (714) 780-8853
  5. ;
  6. ;    THIS PROGRAM IS A GENERAL CASSETTE TAPE LIBRARY MANAGER FOR CP/M.
  7. ;IT ACCEPTS A FUNCTION FOLLOWED BY A FILE NAME FROM THE CONSOLE AND
  8. ;PERFORMS A DISK TO TAPE OR TAPE TO DISK COPY. ANY CP/M FILE MAY BE COPIED.
  9. ;THE TAPE FORMAT IS TARBELL COMPATABLE, HOWEVER THE TAPES PRODUCED BY
  10. ;TAPELIB ARE NOT EASILY LOADED BY OTHER TARBELL INPUT ROUTINES.
  11. ;TAPE FILES ARE NAMED AND SPACE IS PROVIDED FOR EXTENSIVE COMMENTS.
  12. ;
  13. ;            -- COMMAND FORMATS --
  14. ;
  15. ;        DISK TO TAPE
  16. ;    TAPELIB TAPE:=FILENAME.TYP  'OPTIONAL DESCRIPTION OR COMMENTS'
  17. ;    TAPELIB TAPE:=A:FILENAME.TYP    BLOCK
  18. ;    TAPELIB TAPE:=B:FILENAME.TYP       NODISPLAY
  19. ;
  20. ;        TAPE TO DISK
  21. ;    TAPELIB DISK:=FILENAME.TYP
  22. ;    TAPELIB A:=FILENAME.TYP
  23. ;    TAPELIB B:=FILENAME.TYP
  24. ;
  25. ;
  26. ;        EXECUTE FILE 
  27. ;    TAPELIB RUN:=FILENAME.COM
  28. ;
  29. ;        WRITE SYNC
  30. ;    TAPELIB TAPE:=SYNC
  31. ;
  32. ;
  33. ;    TAPELIB MAY ALSO BE LOADED LIKE PIP, BY SIMPLY TYPING TAPELIB.
  34. ;THE PROGRAM WILL LOAD, PRINT A TITLE THEN A * PROMPT. THE COMMANDS
  35. ;GIVEN ABOVE MAY THEN BE ENTERED WITHOUT THE WORD TAPELIB.
  36. ;
  37. ;   FILES MAY BE RENAMED OR SIMPLY VERIFIED (NO ACTUAL TRANSFER) DURING
  38. ;ALL TAPE TO DISK OPERATIONS. A COM FILE MAY ALSO BE RUN FROM TAPE
  39. ;WITHOUT FIRST LOADING IT TO DISK. THE SYNC OPTION WRITES 65K OF SYNC
  40. ;BYTES ON THE TAPE.
  41. ;
  42. ;    TAPELIB DISK:=FILENAME.TYP   RENAME NEW.NAM
  43. ;    TAPELIB DISK:=FILENAME.TYP    VERIFY
  44. ;    TAPELIB DISK:=FILENAME.COM      RUN   NODISPLAY
  45.  
  46. ;  (RENAME,VERIFY,RUN AND THE FILE NAME ARE FREE FORMAT AND MAY BE  
  47. ;ANYWHERE IN THE COMMENT FIELD). A FILE MUST BE TYPE COM TO BE RUN.
  48. ;NODISPLAY IN THE COMMENT FIELD TURNS OFF THE DISPLAY OF THE FILE ON
  49. ;THE TERMINAL DURING TRANSFER OPERATIONS.
  50. ;
  51. ;    A TOTAL OF 128 BYTES ARE AVAILABLE FOR THE COMMAND AND COMMENTS.
  52. ;WHEN COPYING TAPE TO DISK COMMENTS ARE OMITTED. DURING ALL TAPE TRANSFER
  53. ;OPERATIONS THE CONTENTS OF THE FILE ARE DISPLAYED ON THE CONSOLE. NON
  54. ;DISPLAYABLE CHARACTERS DISPLAY AS PERIODS. THE NAMES AND COMMENTS OF
  55. ;THE FILES SKIPPED OVER ARE DISPLAYED DURING THE SEARCH. NORMALLY
  56. ;FILES ARE NOT BLOCKED ON TAPE BUT READ INTO MEMORY IN THEIR ENTIRETY.
  57. ;IF A FILE WILL NOT FIT IN MEMORY IT WILL BE WRITTEN OUT IN 1K BLOCKS.
  58. ;
  59. ;    FILES ARE DISPLAYED ON THE CONSOLE FOR VERIFICATION DURING
  60. ;ALL TRANSFER OPERATIONS. NON DISPLAYABLE CHARACTERS DISPLAY AS PERIODS.
  61. ;THE CONSOLE DEVICE MUST BE CAPABLE OF OPERATING AT A MINIMUM OF
  62. ;4800 BAUD OR ERRORS WILL OCCUR. THE DISPLAY FEATURE MUST BE DISABLED
  63. ;IF SLOW TERMINALS ARE USED.
  64. ;
  65. ;            -- TAPE FORMAT--
  66. ;
  67. ;    1. START BYTES        03CH  (600)
  68. ;    2. SYNC BYTE        06EH
  69. ;    3. DECODE BYTE        0FFH  CONTROLS DISPLAY
  70. ;    4. TYPE BYTE        0 1 OR 2
  71. ;    5. LENGTH BYTE        THE NUMBER OF 256 BYTE RECORDS
  72. ;    6. NAME            CP/M NAME 11 BYTES  (NAME....TYP)
  73. ;    7. COMMENT        110 BYTES PROVIDED, BLANK (20H) IF NOT ENTERED
  74. ;    8. DATA            MULTIPLES OF 256 BYTE RECORDS
  75. ;    9. CHECKSUM        ONE BYTE TARBELL CHECKSUM
  76. ;
  77. ;    A STRING OF 600 START BYTES PROVIDES AT LEAST 3 SEC OF 'LEADER'
  78. ;BETWEEN RECORDS ON THE TAPE. ALL THE MEMORY BETWEEN THE END OF THE
  79. ;PROGRAM AND THE OPERATING SYSTEM, IS USED AS A FILE BUFFER. IF A
  80. ;FILE IS TOO LARGE TO FIT IN THE AVAILABLE MEMORY, IT WILL BE
  81. ;WRITTEN ON TAPE IN 1K BLOCKS DURING DISK TO TAPE TRANSFERS.
  82. ;READING AND WRITING BLOCKED TAPES TAKES ABOUT TWICE AS LONG AS READING
  83. ;OR WRITING UNBLOCKED TAPES. PROGRAMS MAY NOT BE RUN DIRECTLY FROM
  84. ;BLOCKED TAPES. ENTERING THE WORD 'BLOCK' IN THE DESCRIPTION FIELD
  85. ;OF A DISK TO TAPE COMMAND WILL FORCE BLOCKING OF ALL FILES THAT
  86. ;WILL NOT FIT IN A 16K CP/M SYSTEM.
  87. ;
  88. ;
  89. ;    THE PROGRAM WAS ASSEMBLED USING A Z-80 MACRO ASSEMBLY PROGRAM,
  90. ;HOWEVER ONLY 8080 INSTRUCTIONS WERE USED SO THE PROGRAM WILL
  91. ;RUN ON EITHER AN 8080 OR Z-80 BASED PROCESSOR.
  92. ;
  93.     .XLIST
  94. ;
  95.     ;    --------  MACROS   -------
  96. ;
  97. ;
  98. ;   1.   FILL - FILL A BLOCK OF MEMORY WITH A CONSTANT MAX 64K
  99. ;
  100.     .DEFINE FILL [START,END,CONST(0)] = [
  101.     LXI    H,START        ;;SET START ADDR
  102.     .IFB    [END],[
  103.     XRA    A
  104.     MOV    M,A]        ;;STORE ONE BYTE IF NO END
  105.     .IFNB    [END],[
  106.     LXI    D,END-START+1    ;;SET LENGTH
  107.     MVI    A,CONST        ;;LOAD CONSTANT IN A
  108.     MOV    M,A        ;;STORE THE CONST
  109.     INX    H        ;;INCR H
  110.     DCX    D        ;;DECR LENGTH
  111.     MOV    A,D
  112.     ORA    E        ;;TEST LENGTH = ZERO
  113.     JNZ    .-7]]        ;;REPEAT IF DE AND HL NOT EQUAL
  114. ;
  115. ;   1.5  FILLI - FILL INDIRECT A BLOCK OF MEMORY WITH A CONSTANT
  116. ;
  117.     .DEFINE FILLI [START,END,CONST(0),%FI] = [
  118.     LHLD    START        ;;START ADDR
  119.     LXI    D,END+1        ;;END ADDR
  120. %FI:    MVI    A,CONST        ;;CONSTANT TO A
  121.     MOV    M,A        ;;STORE CONST IN MEMORY
  122.     INX    H        ;;INCR POINTER
  123.     CPHL            ;;COMPARE HL AND DE
  124.     JNZ    %FI]        ;;REPEAT TILL ZERO
  125. ;
  126. ;  2.   CPHL - COMPARE DE AND HL AND SET FLAGS
  127. ;
  128.     .DEFINE CPHL = [
  129.     MOV    A,H
  130.     CMP    D        ;;COMPARE HIGH BYTES
  131.     JNZ    .+5
  132.     MOV    A,L
  133.     CMP    E]        ;;COMPARE LOW BYTES
  134. ;
  135. ;
  136. ;   3.  MOVE - MOVE A BLOCK OF LENGTH LEN FROM SOURCE TO DEST
  137. ;
  138.     .DEFINE MOVE [SOURCE,DEST,LEN] = [
  139.     LXI    D,SOURCE    ;SOURCE
  140.     LXI    H,DEST        ;DEST
  141.     LXI    B,LEN    ;LENGTH
  142.     LDAX    D    ;GET A BYTE
  143.     MOV    M,A    ;STORE IT
  144.     INX    H
  145.     INX    D    ;BUMP POINTERS
  146.     DCX    B    ;DECR LENGTH COUNT
  147.     MOV    A,B
  148.     ORA    C
  149.     JNZ    .-7]    ;TEST DONE?
  150. ;
  151. ;
  152. ;   4. MOVEI - MOVE INDIRECT BLOCK OF LENGTH LEN FROM SOURCE TO DEST
  153. ;
  154.     .DEFINE    MOVEI [SOURCE,DEST,LEN] = [
  155.     .IFDIF [DE] [SOURCE],[
  156.     LHLD    SOURCE        ;SOURCE
  157.     XCHG]
  158.     .IFDIF [HL] [DEST],[
  159.     LHLD    DEST]        ;DESTINATION
  160.     .IFDIF [BC] [LEN],[
  161.     LXI    B,LEN]        ;LENGTH
  162.     LDAX    D        ;GET A BYTE
  163.     MOV    M,A        ;STORE IT
  164.     INX    H
  165.     INX    D        ;BUMP POINTERS
  166.     DCX    B        ;DECR LENGTH COUNT
  167.     MOV    A,B
  168.     ORA    C
  169.     JNZ    .-7]        ;TEST DONE
  170. ;
  171. ;   5.  READTB - READ CHAR STRING INTO INPUT TEXT BUFFER
  172. ;
  173.     .DEFINE READTB [TEXT,MAX(127)] = [
  174.     MVI    C,10
  175.     LXI    D,TEXT
  176.     MVI    A,MAX
  177.     STAX    D    ;SET MAXIMUM BUFFER LENGTH
  178.     CALL    5]
  179. ;
  180. ;   6.  PRINTL - PRINT A LITERAL CHARACTER STRING ENCLOSED IN ' '
  181. ;
  182.     .DEFINE    PRINTL [A$,%OUT] = [
  183.     MVI    C,9
  184.     LXI    D,.+9
  185.     CALL    5
  186.     JMP    %OUT
  187.     .ASCII    'A$'
  188. %OUT:]
  189. ;
  190. ;   7.  PRINT - PRINT TEXT FROM MEMORY TO CONSOLE
  191. ;
  192.     .DEFINE PRINT [B$] = [
  193.     MVI    C,9
  194.     LXI    D,B$
  195.     CALL    5]
  196. ;
  197. ;
  198. ;   7.5 DELMAK - DELETE AND MAKE A DISK FILE
  199. ;
  200.     .DEFINE DELMAK [FCB] = [
  201.     MVI    C,19        ;;DELETE CODE
  202.     LXI    D,FCB
  203.     CALL    5
  204.     MVI    C,22        ;;MAKE CODE
  205.     LXI    D,FCB
  206.     CALL    5
  207.     CPI    0FFH        ;;TEST FOR ERROR
  208.     CMC]            ;;COMPLIMENT CARRY
  209. ;   8.  OPEN - OPEN DISK FILE
  210. ;
  211.     .DEFINE OPEN [NAME] = [
  212.     MVI    C,15
  213.     LXI    D,NAME
  214.     CALL    5
  215.     CPI    0FFH    ;TEST FOR ERROR
  216.     CMC        ;COMPLIMENT CARRY
  217.     JNZ    .+4
  218.     STC]
  219. ;
  220. ;
  221. ;   8.5 CLOSE - CLOSE A DISK FILE
  222. ;
  223.     .DEFINE CLOSE [FCB] = [
  224.     MVI    C,16        ;;CLOSE CODE
  225.     LXI    D,FCB
  226.     CALL    5
  227.     CPI    0FFH        ;;TEST FOR ERROR
  228.     CMC            ;;COMPLIMENT CARRY
  229.     JNZ    .+4
  230.     STC]
  231. ;
  232. ;
  233. ;   9.  READ - READ NEXT DISK FILE
  234. ;
  235.     .DEFINE READ [FCB] = [ 
  236.     MVI    C,20
  237.     LXI    D,FCB
  238.     CALL    5
  239.     ORA    A
  240.     JZ    .+4
  241.     STC]            ;;SET CARRY ON EOF OR ERROR
  242. ;
  243. ;
  244. ;
  245. ;   9.5 WRITE - WRITE NEXT RECORD TO DISK
  246. ;
  247.     .DEFINE WRITE [FCB] = [
  248.     MVI    C,21        ;;WRITE CODE
  249.     LXI    D,FCB
  250.     CALL    5
  251.     ORA    A        ;;SET FLAGS
  252.     JZ    .+4
  253.     STC]            ;;SET CARRY ON ERROR
  254. ;
  255. ;
  256. ;    SEARCH - SEARCH DIRECTORY FOR FIRST FCB THAT MATCHES NAME
  257. ;
  258.     .DEFINE SEARCH [FCB] = [
  259.     MVI    C,17        ;;SEARCH CODE
  260.     LXI    D,FCB
  261.     CALL    5
  262.     CPI    0FFH        ;;FFH = NO MATCH
  263.     CMC            ;;SET CARRY IF NO MATCH
  264. ]
  265. ;
  266. ;    SERNXT - SEARCH DIRECTORY FOR NEXT FCB MATCHING NAME
  267. ;
  268.     .DEFINE SERNXT [FCB] = [
  269.     LXI    D,FCB        ;;NAME OF FILE TO SEARCH FOR
  270.     MVI    C,18        ;;SEARCH NEXT CODE
  271.     CALL    5
  272.     CPI    0FFH        ;;0FFH = NO MATCH
  273.     CMC            ;;SET CARRY IF NO MATCH
  274. ]
  275.  
  276. ;   66.  DELETE - DELETE A DISK FILE
  277. ;
  278.     .DEFINE DELETE [FCB] = [
  279.     MVI    C,19
  280.     LXI    D,FCB
  281.     CALL    5]
  282. ;
  283.  
  284. ;
  285. ;  10.  CONIN [$S] - CONSOLE INPUT TO A
  286. ;
  287.     .DEFINE CONIN [$S] = [
  288.     .IFIDN [$S] [SR], [
  289.         PUSH    H
  290.         PUSH    D
  291.         PUSH    B]
  292.     MVI    C,1
  293.     CALL    5
  294.     .IFIDN [$S] [SR],[
  295.         POP    B
  296.         POP    D
  297.         POP    H]
  298.     ]        ;END MACRO
  299. ;
  300. ;    
  301. ;  11.  CONOUT - CONSOLE OUTPUT FROM A
  302. ;
  303.     .DEFINE CONOUT [$S] = [
  304.     .IFIDN [$S] [SR],[
  305.     PUSH    H
  306.     PUSH    D
  307.     PUSH    B]
  308.     MOV    E,A
  309.     MVI    C,2
  310.     CALL    5
  311.     .IFIDN [$S] [SR],[
  312.     POP    B
  313.     POP    D
  314.     POP    H]
  315. ]        ;END MACRO
  316. ;
  317. ;  12.  INDEX - INDEX AN ADDRESS POINTER BY A CONSTANT
  318. ;
  319.     .DEFINE INDEX [POINTER,INDX] = [
  320.     LHLD    POINTER
  321.     LXI    D,INDX
  322.     DAD    D
  323.     SHLD    POINTER]
  324. ;  13.  FILFCB - FILL IN ID FIELDS OF FCB (FILE NAME ENDED BY ZERO BYTE)
  325. ;        ON EXIT - CARRY SET IF NAME TOO LONG
  326. ;            - HL POINTS TO NEXT BYTE AFTER NAME
  327.  
  328. ;
  329.     .DEFINE FILFCB [FCB,IDSTR,%ERROR,%DONE] = [
  330.     LHLD    IDSTR        ;;POINTER TO NAME STRING
  331.     XCHG
  332.     LXI    H,FCB        ;;ADDR OF FILE CONTROL BLOCK
  333.     .IFN $FCBSW,[
  334.     CALL    FFCB]
  335.     .IFE $FCBSW,[
  336.     CALL    FFCB
  337. $FCBSW    =    1        ;;SET CONDITIONAL ASSEMBLY SWITCH
  338.     JMP    ENDFCB
  339. FFCB:    MVI    M,0        ;CLEAR FIRST BYTE OF FCB
  340.     INX    H
  341.     PUSH    H        ;;SAVE FCB NAME ADDR
  342.     MVI    C,11        ;;SIZE OF NAME
  343.     MVI    A,' '        ;;SPACE TO A
  344.     MOV    M,A        ;;SET NAME FIELD TO SPACES
  345.     INX    H
  346.     DCR    C
  347.     JNZ    .-3
  348.     POP    H        ;;RECOVER NAME ADDR
  349.     MVI    C,8        ;;MAXIMUM SIZE OF NAME+1
  350.     LDAX    D        ;;GET ID BYTE
  351.     CPI    ' '        ;;LEADING SPACES ?
  352.     JNZ    .+7        ;;CONTINUE IF NOT
  353.     INX    D        ;;SKIP LEADING SPACES
  354.     JMP    .-7
  355.     LDAX    D        ;;GET ID BYTE
  356.     CPI    0        ;;IS IT A ZERO BYTE
  357.     JZ    %DONE        ;;YES DONE
  358.     CPI    ' '        ;;IMBEDDED SPACE?
  359.     JZ    %DONE        ;;YES DONE
  360.     CPI    '.'        ;;NAME.TYP SEPARATOR?
  361.     JZ    .+13        ;;YES, PROCESS TYPE
  362.     MOV    M,A        ;;STORE NAME BYTE
  363.     INX    D
  364.     INX    H        ;BUMP POINTERS
  365.     DCR    C        ;DECREMENT MAX COUNT
  366.     JP    .-20        ;LOOP
  367.     JMP    %ERROR        ;ERROR, NAME TOO BIG
  368.     INX    D        ;SKIP OVER '.'
  369.     MOV    A,C
  370.     ORA    A
  371.     JZ    .+8
  372.     INX    H        ;;SKIP TO TYPE FIELD
  373.     DCR    C        
  374.     JNZ    .-2    
  375.     MVI    C,3        ;;SIZE OF TYPE FIELD
  376.     LDAX    D        ;;GET ID BYTE    
  377.     CPI    0        ;;ZERO BYTE?
  378.     JZ    %DONE        ;;YES, DONE
  379.     CPI    ' '        ;;SPACE?
  380.     JZ    %DONE        ;;YES, DONE
  381.     MOV    M,A        ;;STORE TYPE BYTE
  382.     INX    D        ;;BUMP POINTERS
  383.     INX    H        
  384.     DCR    C        ;;DECREMENT MAX COUNT
  385.     JNZ    .-15        ;;LOOP
  386.     JMP    %DONE        ;;DONE
  387.     
  388.     
  389. %ERROR:    STC            ;;SET CARRY
  390. %DONE:    XCHG            ;;POINTER TO END OF NAME
  391.     RET
  392. ENDFCB:]]            ;;END MACRO
  393.  
  394. ;
  395. ;  14.  $INSTR - IN STRING FUNCTION SEARCHES STRING OF LEN LSRT FOR SUBSTRING
  396. ;        RETURNS WITH CARRY SET IF MATCH AND HL POINTING TO END SUBSTR
  397. ;
  398.     .DEFINE $INSTR [STRING,LSTR,SUBSTRING,%STR,%OVER] = [
  399.     LHLD    STRING        ;;GET STRING ADDR
  400.     MVI    B,LSTR        ;;STRING LENGTH
  401.     .IFN    $STRSW,[
  402.     LXI    D,%STR
  403.     MVI    C,%OVER-%STR
  404.     CALL    FSTR
  405.     JMP    %OVER
  406. %STR:    .ASCII    'SUBSTRING'
  407. %OVER:]
  408.     .IFE    $STRSW,[
  409.     LXI    D,%STR
  410.     MVI    C,%OVER-%STR
  411.     CALL    FSTR
  412.     JMP    %END
  413. %STR:    .ASCII    'SUBSTRING'
  414. %OVER:
  415.     $STRSW = 1
  416. FSTR:    MOV    A,B        ;;STRING LEN
  417.     SUB    C        ;;SUBSTR LEN
  418.     CMC
  419.     JM    .+21        ;;SUBSTR LONGER THAN STRING
  420.     MOV    B,A        ;;STRING LENGTH-SUBSTRING LENGTH
  421. INSTR1:    PUSH    H
  422.     PUSH    D
  423.     PUSH    B
  424.     DCR    C        ;;DECR LENGTH COUNT
  425.     JM    .+17        ;;EXIT MATCH FOUND
  426.     LDAX    D        ;;GET A BYTE FROM FIRST STRING
  427.     CMP    M        ;;CONPARE WITH SECOND STRING
  428.     JNZ    .+8        ;;EXIT NO MATCH
  429.     INX    H
  430.     INX    D        ;;INCR ADDR POINTERS
  431.     JMP    .-11        ;;TRY AGAIN
  432.     XRA    A        ;;CLEAR CARRY
  433.     JMP    .+4        ;;EXIT
  434.     STC            ;;SET CARRY
  435.     POP    B
  436.     POP    D
  437.     POP    H
  438.     JC    SSX        ;;MATCH FOUND SET POINTER AND RET
  439.     DCR    B        ;;DECR STRING LEN
  440.     RM            ;;RETURN IF MINUS - NO MATCH
  441.     INX    H        ;;INCR STRING POINTER
  442.     JMP    INSTR1        ;;GO TRY SOME MORE
  443.     RET
  444. SSX:    LXI    D,0
  445.     MOV    E,C
  446.     DAD    D        ;;ADD LENGTH TO POINTER
  447.     STC            ;;SET CARRY
  448.     RET
  449. %END:]]
  450. ;
  451. ;
  452. ;  15.  $MATCH - COMPARE STRING WITH LITERAL AND SET CARRY IF EQUAL
  453. ;
  454.     .DEFINE $MATCH [STR1,STR2,%STR,%OVER] = [
  455.     LXI    H,STR1
  456.     .IFN    $MATSW,[
  457.     LXI    D,%STR
  458.     MVI    C,%OVER-%STR
  459.     CALL    SMATCH
  460.     JMP    %OVER
  461. %STR:    .ASCII    'STR2'
  462. %OVER:]
  463.     .IFE    $MATSW,[
  464.     LXI    D,%STR
  465.     MVI    C,%OVER-%STR
  466.     CALL    SMATCH
  467.     JMP    MATEND
  468. %STR:    .ASCII    'STR2'
  469. %OVER:
  470. $MATSW    =    1        ;;CONDITIONAL ASSEMBLY SWITCH
  471. SMATCH:    DCR    C        ;;DECR LENGTH COUNT
  472.     JM    SM3        ;;EXIT MATCH FOUND
  473.     LDAX    D        ;;GET A BYTE FROM FIRST STRING
  474.     CMP    M        ;;COMPARE WITH SECOND STRING
  475.     JNZ    SM2        ;;EXIT, NO MATCH
  476.     INX    H
  477.     INX    D        ;;INCR ADDR POINTERS
  478.     JMP    SMATCH        ;;TRY AGAIN
  479. SM2:    XRA    A        ;;CLEAR CARRY
  480.     JMP    .+4        ;;EXIT
  481. SM3:    STC            ;;SET CARRY
  482.     RET
  483. MATEND:]]
  484. ;
  485. ;
  486. ;   17.  IMATCH - COMPARE INDIRECT STRINGS OF EQUAL LENGTH SET CARRY IF =
  487. ;
  488.     .DEFINE IMATCH [STR1,STR2,LEN] = [
  489.     LXI    D,STR1        ;;ONE STRING
  490.     .IFDIF    [STR2][HL],[
  491.     LXI    H,STR2]        ;;THE OTHER
  492.     MVI    C,LEN        ;;LENGTH
  493.     DCR    C        ;;DECR LENGTH COUNT
  494.     JM    .+17        ;;MATCH FOUND EXIT
  495.     LDAX    D        ;;BYTE FROM ONE STRING
  496.     CMP    M        ;;COMPARE WITH OTHER STRING
  497.     JNZ    .+8        ;;NO MATCH EXIT
  498.     INX    H
  499.     INX    D        ;;INCR POINTERS
  500.     JMP    .-11        ;;TRY AGAIN
  501.     XRA    A        ;;CLEAR CARRY
  502.     JMP    .+4        ;;EXIT
  503.     STC]            ;;SET CARRY ON MATCH
  504. ;
  505. ;
  506.  
  507. ;   18. GETDRV - INTERROGATE AND SAVE CURRENTLY LOGGED DISK NO
  508. ;
  509.     .DEFINE GETDRV [SAVE] = [
  510.     MVI    C,25
  511.     CALL    5
  512.     STA    SAVE]
  513. ;
  514. ;
  515. ;
  516. ;   19. SETDRV - SET DISK DRIVE NUMBER
  517. ;
  518.     .DEFINE SETDRV [X] = [
  519.     MVI    C,14
  520.     LXI    D,X
  521.     CALL    5]
  522. ;
  523. ;
  524. ;   20. RESDRV - RESTORE SAVED DISK DRIVE NUMBER
  525. ;
  526.     .DEFINE RESDRV [SAVE] = [
  527.     MVI    C,14
  528.     LDA    SAVE
  529.     MOV    E,A
  530.     CALL    5]
  531. ;
  532. ;
  533.     .LIST
  534.     .PABS
  535.     .SALL
  536.     .XSYM
  537.     .LOC    100H        ;SET ORIGIN AT 100
  538. ;
  539. ;SET CONDITIONAL ASSEMBLY SWITCHES
  540. ;
  541. $FCBSW    =    0
  542. $MATSW    =    0
  543. $STRSW    =    0
  544.     LXI    SP,NEWSTK    ;SET UP NEW STACK
  545.     LHLD    6        ;TOP OF MEMORY
  546.     LXI    D,-128
  547.     DAD    D        ;SUBTRACT 128 FOR LAST BLOCK
  548.     LXI    D,5000H        ;MEMORY LIMIT
  549.     CPHL            ;COMPARE DE - HL
  550.     JC    STEND
  551.     XCHG
  552. STEND:    SHLD    MEMEND        ;SET END OF MEMORY
  553.     GETDRV    DRVNO        ;SAVE CURRENTLY LOGGED DISK DRIVE NO
  554.     STA    NEWDRV        ;SAVE IT IN NEWDRV TOO
  555.     LDA    80H        ;BUFFER ALREADY FILLED?
  556.     ORA    A
  557.     JNZ    START
  558.     PRINT    CRLF
  559.     PRINTL    'TAPELIB UTILITY VERS 1.1$'
  560.     PRINT    CRLF
  561.     PRINTL    'COPYRIGHT 1977 BY S. J. SINGER$'
  562. NEWIN:    PRINT    CRLF2
  563.     PRINTL    '*$'
  564.     MVI    A,0FFH        ;SET SWITCH TO RETURN HERE AGAIN
  565.     STA    INFLAG
  566.     FILL    80H,0FFH    ;ZERO INPUT BUFFER
  567.     READTB    80H        ;READ TEXT INTO BUFFER
  568.     LDA    81H        ;POINTS TO END OF INPUT
  569.     INR    A
  570.     STA    80H        ;MOVE IT TO 80H
  571.     XRA    A
  572.     STA    DISFLG        ;TURN OFF DISPLAY
  573.     STA    DFLAG1
  574.     STA    VERFLG        ;RESET VERIFY FLAG
  575.     STA    AMBIG        ;RESET AMBIGUOUS FILE NAME FLAG
  576.     STA    FAMBIG        ;RESET FIRST AMBIGUOUS FILE FLAG
  577.     MVI    A,65
  578.     STA    BCOUNT        ;RESET DISPLAY CHAR PER LINE
  579.     MVI    A,88H
  580.     STA    SLOC1        ;RESET FILE NAME POINTER
  581. START:    FILL    FCB,FCB+32    ;ZERO ALL FIELDS OF FCB
  582.     $INSTR    IPOINT,120,'BLOCK'    ;BLOCK TAPE ?
  583.     JNC    NODIS
  584.     LXI    H,3000H
  585.     SHLD    MEMEND        ;SET MEMORY LIMIT
  586. NODIS:    $INSTR    IPOINT,120,'NODISPLAY'    ;TURN OFF DISPLAY ?
  587.     JNC    MAT1
  588.     MVI    A,0FFH
  589.     STA    DFLAG1        ;TURN OFF DISPLAY FOR SLOW TERMINALS
  590. MAT1:    $MATCH    82H,'TAPE:='
  591.     JC    DT1
  592.     $MATCH    82H,'DISK:='
  593.     JC    TDISK
  594.     $MATCH    82H,'A:='
  595.     JC    ADISK
  596.     $MATCH    82H,'B:='
  597.     JC    BDISK
  598.     $MATCH    82H,'RUN:='
  599.     JC    RUNFIL        ;GO TO EXEC FILE IF TYPE COM
  600. INERR:    PRINT    CRLF
  601.     PRINTL    'ERROR - NO SUCH DESTINATION$'
  602.     JMP    MOREIN    ;ERROR IN INPUT COMMAND STRING EXIT
  603. ;
  604. ;    SELECT DISK DRIVE
  605. ;
  606. DT1:    $MATCH    88H,'SYNC'    ;TEST FOR WRITE SYNC STREAM
  607.     JC    SYNC
  608.     $MATCH    88H,'A:'    ;DRIVE A
  609.     JNC    DT2
  610.     XRA    A        ;0 - DRIVE A
  611.     STA    NEWDRV
  612.     JMP    DOWN
  613. DT2:    $MATCH    88H,'B:'    ;DRIVE B
  614.     JNC    DTAPE
  615.     MVI    A,1        ;1 - DRIVE B
  616.     STA    NEWDRV
  617. DOWN:    MOVE    84H,82H,120    ;SHIFT BUFFER DOWN TWO BYTES
  618.     LXI    H,80H        ;POINTS TO LENGTH OF COMMENT
  619.     DCR    M
  620.     DCR    M        ;DECR LENGTH BY 2
  621. ;
  622. ;  DTAPE - START OF DISK TO TAPE ROUTINE
  623. ;
  624. DTAPE:    FILFCB    FCB,SLOC1    ;FILL IN FCB FROM INPUT BUFFER
  625.     JC    NAMERR        ;ERROR IN NAME PRINT ERROR MESSAGE
  626.     PUSH    H        ;POINTER TO START OF COMMENT
  627.     FILL    FILBUF,FILBUF+128,20H   ;BLANK COMMENT FIELD OF FILE
  628.     LDA    80H        ;POINTS TO LENGTH OF COMMENT
  629.     ADI    81H
  630.     LXI    H,0        ;ZERO HL
  631.     MOV    L,A        ;HL POINTS TO END OF COMMENT
  632.     POP    D        ;POINTS TO START OF COMMENT
  633.     LXI    B,FILBUF+11    ;POINTS TO OUTPUT BUFFER
  634. MOVCOM:    CPHL            ;FINISHED MOVE ?
  635.     JZ    ENDMOV
  636.     LDAX    D        ;GET BYTE OF COMMENT
  637.     STAX    B        ;STORE IT
  638.     INX    D
  639.     INX    B
  640.     JNZ    MOVCOM        ;LOOP BACK
  641. ENDMOV:    CALL    SCANFCB        ;CHECK FOR AMBIGUOUS FILE NAME
  642.     JNC    DTAPE1
  643.     MOVE    FCB,AMBNAM,12    ;SAVE AMBIGUOUS FILE NAME
  644.     MVI    A,0FFH
  645.     STA    AMBIG        ;SET AMBIGUOUS NAME FLAG
  646.     RESDRV    NEWDRV        ;SELECT NEW DRIVE IF ANY
  647.     CALL    GETNAM
  648. DAM:    LXI    D,FCB        ;POINT TO FCB
  649.     MVI    C,12        ;LENGTH
  650. MNAM:    MOV    A,M
  651.     STAX    D
  652.     INX    H
  653.     INX    D
  654.     DCR    C
  655.     JNZ    MNAM        ;MOVE NAME
  656.     FILL    FCB+12,FCB+8    ;ZERO REST OF FCB
  657. DTAPE1:    MOVE    FCB+1,FILBUF,11    ;MOVE NAME TO OUTPUT BUFFER
  658.     RESDRV    NEWDRV        ;SELECT NEW DRIVE
  659.     OPEN    FCB
  660.     JNC    LDFIL
  661. OPNERR:    PRINT    CRLF
  662.     LDA    NEWDRV
  663.     ORA    A
  664.     JNZ    OER1
  665.     PRINTL    'NO FILE BY THAT NAME ON DRIVE A$'
  666.     JMP    MOREIN
  667. OER1:    PRINTL    'NO FILE BY THAT NAME ON DRIVE B$'
  668.     JMP    MOREIN
  669. LDFIL:    LXI    H,FILBUF+128    ;SET DISK FILE BUFFER POINTER
  670.     SHLD    BPOINT
  671.     LXI    H,80H
  672.     SHLD    IPOINT        ;RESET INPUT BUFFER POINTER TO 80H
  673.     LXI    H,0
  674.     SHLD    NBLOCKS        ;INITIALIZE BLOCK COUNT TO ZERO
  675. LD1:    READ    FCB        ;READ A RECORD FROM DISK
  676.     JC    ENDFIL        ;EXIT IF ERROR OR EOF
  677.     MOVEI    IPOINT,BPOINT,128    ;MOVE BLOCK TO BUFFER
  678.     INDEX    NBLOCKS,1    ;INDEX BLOCK COUNT BY ONE
  679.     INDEX    BPOINT,128    ;INDEX BUFFER POINTER BY 128
  680.     XCHG
  681.     LHLD    MEMEND        ;TEST FOR MEMORY OVERFLOW
  682.     CPHL            ;COMPARE DE AND HL
  683.     JNC    LD1        ;BACK TO READ LOOP
  684. MEMFUL:    PRINT    CRLF2
  685.     PRINTL    'BLOCKED TAPE REQUESTED OR$'
  686.     PRINT    CRLF
  687.     PRINTL    'FILE TOO LARGE FOR MEMORY$'
  688.     PRINT    CRLF
  689.     PRINTL    'WRITING BLOCKED OUTPUT TAPE$'
  690.     LDA    FAMBIG
  691.     ORA    A
  692.     JNZ    GOBLK        ;DISPLAY MESS ONLY FOR FIRST BLK
  693.     MVI    A,-1
  694.     STA    FAMBIG        ;START TAPE DISPLAY OFF
  695.     CALL    STARTW        ;DISPLAY START MESSAGE
  696. GOBLK:    PRINT    CRLF2
  697.     MOVE    FILBUF,FILBUF+1280,128    ;SAVE COMMENT FIELD
  698.     JMP    BLKOUT        ;WRITE BLOCKED OUTPUT TAPE
  699. ENDFIL:    CPI    1        ;TEST FOR EOF
  700.     JZ    TAPE
  701. RDERR:    PRINT    CRLF
  702.     PRINTL    'DISK READ ERROR$'
  703.     JMP    MOREIN        ;EXIT
  704. TAPE:    LHLD    NBLOCKS        ;GET NO OF 128 BYTE BLOCKS READ
  705.     INX    H
  706.     INX    H        ;ADD 2 FOR ROUNDING
  707.     MOV    A,H        ;SHIFT RIGHT 1 BIT DOUBLE
  708.     RAR
  709.     MOV    A,L
  710.     RAR
  711.     PUSH    PSW        ;STACK HAS NO OF 256 BYTE BLOCKS
  712.     JC    PM1        ;CARRY SET, PRINT MESSAGE
  713.     LHLD    BPOINT        ;NOT SET, FILL LAST 128 BYTES WITH ^Z
  714.     PUSH    H
  715.     INDEX    BPOINT,128
  716.     XCHG            ;END OF BLOCK IN D
  717.     LHLD    MEMEND        ;TOP OF MEMORY
  718.     CPHL
  719.     JC    MEMFUL        ;MEMORY FILLED PRINT ERROR MESSAGE
  720.     POP    H        ;BEGINING OF BLOCK IN HL
  721. LF1:    MVI    A,1AH        ;CONTROL Z
  722.     MOV    M,A        ;STORE IT IN MEMORY
  723.     INX    H
  724.     CPHL            ;LIMIT REACHED
  725.     JNZ    LF1
  726. PM1:    LDA    FAMBIG
  727.     ORA    A
  728.     JNZ    PMX        ;NO START MESSAGE
  729.     CALL    STARTW        ;DISPLAY MESSAGE
  730.     MVI    A,0FFH
  731.     STA    FAMBIG        ;SET SWITCH FOR DISPLAY OFF
  732. PMX:    CALL    WRID        ;WRITE AN ID BLOCK ON TAPE
  733.     POP    B        ;NO OF 256 BYTE BLOCKS IN B
  734.     LXI    H,FILBUF
  735.     MVI    C,1        ;RECORD TYPE
  736.     CALL    TAPOUT        ;WRITE THE RECORD
  737. PMY:    LDA    AMBIG        ;AMBIGUOUS NAME FLAG
  738.     ORA    A
  739.     JZ    PM2        ;NOT SET THEN EXIT
  740.     CALL    GETNAM        ;SEARCH DIR WITH PREVIOUS NAME
  741.     MOVE    AMBNAM,FCB,12    ;AMBIG NAME FOR NEXT SEARCH
  742.     CALL    GETNEXT        ;SEARCH DIR FOR NEXT NAME
  743.     JC    PM2        ;EXIT IF NO MORE NAMES
  744.     PUSH    H
  745.     PRINT    CRLF2        ;SPACE AND RING BELL
  746.     POP    H
  747.     JMP    DAM        ;WRITE THE FILE ON TAPE
  748. PM2:    CALL    STOP        ;DISPLAY STOP MESSAGE
  749.     JMP    MOREIN        ;EXIT
  750. ;
  751. ;    THIS ROUTINE WRITES BLOCKED OUTPUT TAPES FOR FILES
  752. ;    TOO LARGE FOR MEMORY
  753. ;
  754. BLKOUT:    CLOSE    FCB
  755.     FILL    FCB+12,FCB+8,0
  756.     FILL    FILBUF+128,FILBUF+1024,1AH
  757.     OPEN    FCB        ;POSITION FILE TO FIRST RECORD
  758.     LXI    H,FILBUF+128
  759.     SHLD    BPOINT
  760.     LXI    H,80H
  761.     SHLD    IPOINT        ;RESET DATA TRANSFER POINTERS
  762.     MVI    A,0FFH
  763.     STA    FIRST        ;INDICATE FIRST RECORD
  764.     MVI    A,15
  765.     STA    BLKBLK        ;RESET BLOCK COUNTER
  766. RBEG:    MVI    A,1
  767.     STA    BLOCK        ;SET BLOCK COUNT TO 1
  768. RLOOP:    READ    FCB        ;READ A RECORD FROM DISK
  769.     JC    FEND        ;CARRY SET ON EOF OR ERROR
  770.     MOVEI    IPOINT,BPOINT,128    ;MOVE BLOCK
  771.     LDA    BLOCK
  772.     CPI    8
  773.     JZ    TAPWRT        ;IF 8 RECORDS WRITE TAPE
  774.     INR    A
  775.     STA    BLOCK        ;INCR BLOCK COUNT
  776.     INDEX    BPOINT,128    ;INCR  ADDR BY 128
  777.     JMP    RLOOP
  778. FEND:    CPI    1
  779.     JNZ    RDERR        ;DISK READ ERROR
  780.     MVI    C,2        ;TYPE
  781.     XRA    A        ;CLEAR CARRY
  782.     LDA    BLOCK        ;BLOCK COUNT
  783.     INR    A
  784.     RAR            ;NO OF 256 BYTE BLOCKS
  785.     MOV    B,A        ;STORE IN B
  786.     LXI    H,FILBUF    ;BUFFER POINTER
  787.     CALL    WRSPAC        ;WRITE SPACER BLOCK
  788.     CALL    TAPOUT
  789.     MOVE    FILBUF+1280,FILBUF,128    ;RESTORE COMMENT FIELD
  790.     JMP    PMY        ;PRINT MESSAGE AND EXIT
  791. TAPWRT:    LDA    FIRST
  792.     ORA    A        ;IS THIS THE FIRST RECORD
  793.     JNZ    BLK1        ;YES, WRITE IT WITH HEADER
  794.     MVI    C,1
  795.     MVI    B,4        ;BLOCK COUNT
  796. BLKN:    LXI    H,FILBUF    ;BUFFER POINTER
  797.     CALL    WRSPAC        ;WRITE SPACER BLOCK
  798.     CALL    TAPOUT        ;WRITE TAPE
  799.     FILL    FILBUF,FILBUF+1024,1AH
  800.     LXI    H,FILBUF
  801.     SHLD    BPOINT
  802.     JMP    RBEG        ;BACK FOR MORE DISK INPUT
  803. BLK1:    CALL    WRID        ;WRITE FILE HEADER
  804.     MVI    C,0        ;FIRST BLOCK TYPE 0
  805.     MVI    B,5        ;5 BLOCKS WITH HEADER
  806.     XRA    A
  807.     STA    FIRST        ;NOT FIRST
  808.     JMP    BLKN        ;BACK TO OUTPUT
  809. ;
  810. ;
  811. ;    RUN TAPE FILE
  812. ;
  813. RUNFIL:    LXI    H,87H
  814.     SHLD    SLOC1        ;POINTER TO FILE NAME
  815.     MVI    A,0FFH
  816.     STA    RUNFLG        ;SET RUN FLAG TRUE
  817.     JMP    TDISK
  818. ;
  819. ;    SELECT DISK DRIVE
  820. ;
  821. ADISK:    XRA    A        ;0 - DRIVE A
  822.     STA    NEWDRV
  823.     JMP    BD1
  824. BDISK:    MVI    A,1        ;1 - DRIVE B
  825.     STA    NEWDRV
  826. BD1:    LXI    H,85H
  827.     SHLD    SLOC1        ;POINTER TO NAME
  828. ;
  829. ;  TDISK - START OF TAPE TO DISK ROUTINE
  830. ;
  831. TDISK:    FILFCB    FCB,SLOC1    ;FILL IN FCB FROM INPUT BUFFER
  832.     JC    NAMERR        ;FILE NAME ERROR PRINT MESS
  833.     CALL    SCANFCB        ;CONVERT * TO ? IN AMBIG FILE NAMES
  834.     JNC    TDISK1
  835.     MVI    A,-1
  836.     STA    AMBIG        ;SET AMBIGUOUS NAME FLAG
  837.     MOVE    FCB,AMBNAM,12    ;SAVE AMBIG NAME
  838. TDISK1:    MOVE    80H,FILBUF,128    ;SAVE NAME AND COMMENT, RESDRV MAY USE BUFFER
  839.     RESDRV    NEWDRV        ;LOAD NEW DRIVE NO IF SELECTED
  840.     MOVE    FILBUF,80H,128    ;RESTORE NAME AND COMMENT
  841.     PRINT    CRLF2
  842.     PRINTL    'START CASSETTE TAPE - TYPE CARRIAGE RETURN$'
  843.     PRINT    CRLF2
  844.     CONIN            ;WAIT FOR CONSOLE INPUT
  845.     CPI    3        ;CONTROL C ?
  846.     JZ    MOREIN        ;RETURN TO MONITOR
  847.     JMP    TAPIN        ;TO TAPE INPUT ROUTINE
  848. ;
  849. ;   CASW - CASSETTE OUTPUT ROUTINE  (DATA IN A)
  850. ;
  851. CASW:    PUSH    H        ;SAVE REGS
  852.     PUSH    D
  853.     PUSH    B
  854.     PUSH    PSW
  855.     CALL    ESCAPE        ;CHECK FOR CONTROL C
  856. CAS1:    IN    CASC        ;GET STATUS
  857.     ANI    20H
  858.     JNZ    CAS1        ;WAIT FOR STATUS READY
  859.     POP    PSW        ;DATA BACK TO A
  860.     PUSH    PSW        ;SAVE IT AGAIN
  861.     OUT    CASD        ;WRITE BYTE TO TAPE
  862.     OUT    0FFH        ;OUT TO LIGHTS
  863.     LXI    H,CKSUM        ;MEMORY ADDR OF CHECKSUM
  864.     ADD    M        ;ADD TO A
  865.     STA    CKSUM        ;STORE IT BACK
  866.     POP    PSW        ;GET BACK DATA
  867.     CALL    DISPLY        ;OUTPUT TO CONSOLE
  868.     POP    B        ;RESTORE REGISTERS
  869.     POP    D
  870.     POP    H
  871.     RET
  872. CASC    ==    6EH        ;CASSETTE STATUS PORT
  873. CASD    ==    6FH        ;CASSETTE DATA   PORT
  874. ;
  875. CASR:    PUSH    H        ;SAVE REGISTERS
  876.     PUSH    D
  877.     PUSH    B
  878. ETEST:    CALL    ESCAPE        ;CHECK FOR CONTROL C
  879. READCT:    IN    CASC        ;READ CASSETTE STATUS
  880.     ANI    10H        ;CHECK BIT 4
  881.     JNZ    ETEST        ;WAIT TILL READY
  882.     IN    CASD        ;READ CASSETTE DATA
  883.     PUSH    PSW        ;SAVE IT
  884.     OUT    0FFH        ;OUT TO LIGHTS
  885.     LXI    H,CKSUM        ;POINTER TO CKSUM
  886.     ADD    M        ;ADD IT TO DATA
  887.     STA    CKSUM        ;STORE IT BACK
  888.     POP    PSW        ;GET BACK DATA
  889.     PUSH    PSW        ;SAVE IT AGAIN
  890.     CALL    DISPLY        ;OUT TO CONSOLE
  891.     POP    PSW        ;GET BACK DATA
  892.     POP    B
  893.     POP    D
  894.     POP    H        ;RESTORE REGISTERS
  895.     RET
  896. ;  ESCAPE - TEST FOR CONTROL C AND RETURN TO MONITOR
  897. ;
  898. ESCAPE:    MVI    C,11
  899.     CALL    5
  900.     ANI    1
  901.     RZ            ;RETURN IF LOW BIT NOT SET
  902.     CONIN
  903.     CPI    3        ;TEST FOR ^C
  904.     JZ    MOREIN        ;EXIT TO MONITOR OR BACK TO INPUT
  905.     RET
  906. ;
  907. ;
  908. ;   DISPLY - OUTPUT A TO CONSOLE AND SUBSTITUTE . FOR ^ CHARACTERS
  909. ;
  910. DISPLY:    PUSH    PSW        ;SAVE DATA
  911.     LDA    DISFLG        ;DISPLAY FLAG
  912.     ORA    A
  913.     JZ    YSKIP        ;OUT IF ZERO
  914.     LDA    DFLAG1
  915.     ORA    A        ;DISPLAY OFF FOR SLOW TERMINALS
  916.     JNZ    YSKIP        ;OUT IF NOT ZERO
  917.     LDA    BCOUNT        ;COUNT OF BYTES PER LINE
  918.     DCR    A        ;DECR BY ONE
  919.     STA    BCOUNT        ;STORE IT BACK
  920.     JNZ    USKIP        ;CONTINUE IF NOT END OF LINE
  921.     PRINT    CRLF
  922.     MVI    A,64        ;CHAR PER LINE
  923.     STA    BCOUNT        ;RESET COUNTER
  924. USKIP:    POP    PSW        ;GET BACK DATA
  925.     CPI    7FH        ;COMPARE WITH RUBOUT
  926.     JP    VSKIP        ;PRINT PERIOD
  927.     CPI    20H        ;COMPARE WITH SPACE
  928.     JP    XSKIP        ;SKIP SUBSTITUTION
  929. VSKIP:    MVI    A,2EH        ;ASCII PERIOD
  930. XSKIP:    CONOUT            ;OUT TO CONSOLE
  931.     RET
  932. YSKIP:    POP    PSW
  933.     RET
  934. ;   NAME ERROR IN FILE NAME - PRINT ERROR MESSAGE
  935. ;
  936. NAMERR:    PRINT    CRLF
  937.     PRINTL    'ERROR IN FILE NAME$'
  938.     JMP    MOREIN        ;EXIT BACK TO MONITOR
  939. ;
  940. ;
  941. ;
  942. ;   TAPEOUT - OUTPUT BLOCK OF TAPE IN TARBELL FORMAT
  943. ;
  944. TAPOUT:    PUSH    H        ;SAVE POINTER
  945.     LXI    H,BLKBLK    ;POINT TO BLOCK COUNT
  946.     INR    M        ;INCR BY ONE
  947.     MVI    A,16        ;BLOCK LIM 1
  948.     CMP    M
  949.     JZ    T0        ;WRITE SPACER BLOCK
  950.     INR    A
  951.     CMP    M        ;IS COUNT 18
  952.     JNZ    T1        ;NO EXTRA SPACE BLOCK
  953.     MVI    M,1        ;SET BLOCK COUNT TO ONE
  954. T0:    CALL    WRSPAC        ;WRITE SPACE BLOCK
  955.     CALL    WRSPAC        ;WRITE SPACE BLOCK
  956. T1:    POP    H        ;RESTORE POINTER
  957.     MVI    A,3CH        ;START BYTE
  958.     CALL    CASW        ;WRITE IT OUT
  959.     MVI    A,0E6H        ;SYNC BYTE
  960.     CALL    CASW        ;WRITE IT
  961.     XRA    A
  962.     STA    CKSUM        ;ZERO CHECKSUM
  963.     MVI    A,0FFH        ;DECODE BYTE
  964.     CALL    CASW        ;WRITE IT
  965.     MOV    A,C        ;TYPE BYTE
  966.     CALL    CASW        ;WRITE IT TO TAPE
  967.     MOV    A,B        ;NO OF 256 BYTE BLOCKS
  968.     CALL    CASW        ;WRITE IT OUT
  969.     MVI    A,0FFH        ;SET DISPLAY FLAG
  970.     STA    DISFLG
  971. T2:    MVI    C,0        ;BLOCK LENGTH IN BYTES - 1
  972. T3:    MOV    A,M        ;GET A BYTE FROM MEMORY
  973.     CALL    CASW        ;WRITE IT TO CASSETTE
  974.     INX    H
  975.     DCR    C
  976.     JNZ    T3        ;LOOP TILL END OF BLOCK
  977.     DCR    B
  978.     JNZ    T2        ;LOOP TILL ALL BLOCKS DONE
  979. T4:    XRA    A
  980.     STA    DISFLG        ;TURN OFF DISPLAY
  981.     LDA    CKSUM
  982.     CALL    CASW        ;WRITE CHECKSUM
  983.     RET            ;BYE
  984. ;
  985. ;  TAPIN - TAPE INPUT ROUTINE
  986. ;
  987. TAPIN:    XRA    A
  988.     STA    DISFLG        ;TURN OFF DISPLAY
  989.     CALL    RDID        ;SEARCH TAPE FOR ID BLOCK
  990.     XRA    A        ;ZERO
  991.     STA    CKSUM        ;ZERO CHECKSUM
  992.     MVI    A,10H
  993.     OUT    CASC        ;RESET RECEIVER
  994.     CALL    CASR        ;READ DECODE BYTE
  995.     CPI    0FFH        ;CHECK IT
  996.     JNZ    TAPIN
  997.     CALL    CASR        ;READ TYPE BYTE
  998.     STA    TYPE        ;SAVE IT
  999.     CPI    3        ;CHECK TYPE < 3
  1000.     JP    TAPIN
  1001.     CALL    CASR        ;READ LENGTH
  1002.     LXI    H,0
  1003.     MOV    L,A        ;NO OF 256 BYTE BLOCKS ON TAPE
  1004.     MOV    B,A        ;SAVE IT IN B
  1005.     DAD    H        ;SHIFT LEFT 1
  1006.     DCX    H        ;NUMBER OF 128 BYTE BLOCKS (FOR DISK)
  1007.     SHLD    NBLOCKS        ;STORE TO MEMORY
  1008.     MVI    A,0FFH        ;.TRUE.
  1009.     STA    DISFLG        ;TURN ON DISPLAY FLAG
  1010.     LXI    H,FILBUF    ;BUFFER POINTER
  1011.     LXI    D,1        ;BLOCK COUNT FOR NAME CHECK
  1012. RD1:    MVI    C,128        ;NO BYTES PER BLOCK - 1
  1013. RD2:    CALL    CASR        ;READ A BYTE
  1014.     MOV    M,A        ;STORE IT
  1015.     INX    H
  1016.     DCR    C        ;DECR LENGTH
  1017.     JNZ    RD2        ;LOOP BACK
  1018.     DCX    D
  1019.     MOV    A,D        ;DECR BLOCK COUNT FOR NAME CHECK
  1020.     ORA    E
  1021.     JZ    NAMCHK        ;COMPARE NAME FROM TAPE WITH FCB
  1022. GOON:    DCR    B        ;DECR NO OF BLOCKS
  1023.     MVI    C,0        ;NO OF BYTES PER BLOCK - 1
  1024.     JNZ    RD2        ;LOOP BACK
  1025.     SHLD    ENDF        ;SAVE LOCATION OF LAST BYTE READ
  1026.     LDA    CKSUM        ;GET CHECKSUM FROM MEMORY
  1027.     MOV    B,A        ;STORE IT TEMPORARILY IN B
  1028.     XRA    A        ;ZERO
  1029.     STA    DISFLG        ;TURN OFF DISPLAY
  1030.     CALL    CASR        ;READ CHECKSUM FROM TAPE
  1031.     SUB    B        ;COMPARE IT WITH MEMORY
  1032.     JNZ    TPERR        ;CHECKSUM ERROR
  1033.     LDA    AMBIG        ;CHECK AMBIG FLAG
  1034.     ORA    A
  1035.     JNZ    PCR2        ;TO DISK ROUTINE
  1036.     CALL    STOP        ;DISPLAY STOP MESSAGE
  1037.     JMP    WDISK        ;TO DISK WRITE ROUTINE
  1038. PCR2:    PRINT    CRLF2        ;CARRIAGE RET
  1039.     JMP    WDISK        ;TO DISK WRITE ROUTINE
  1040. ;
  1041. TPERR:    PRINT    BELL
  1042.     PRINTL    'CHECKSUM ERROR$'
  1043.     PRINT    CRLF
  1044.     PRINTL    'TO RESTART - REWIND TAPE AND TYPE CARRIAGE RETURN$'
  1045.     PRINT    CRLF
  1046.     CONIN            ;READ CONSOLE
  1047.     CPI    3        ;CONTROL C ?
  1048.     JZ    MOREIN        ;RETURN TO MONITOR
  1049.     JMP    TAPIN        ;BACK TO TAPE INPUT ROUTINE
  1050. ;
  1051. ;
  1052. NAMCHK:    PUSH    H
  1053.     PUSH    D
  1054.     PUSH    B
  1055.     PRINT    CRLF
  1056.     LXI    H,FILBUF    ;SET POINTERS
  1057.     LXI    D,FCB+1
  1058.     MVI    C,11
  1059. NAMC1:    DCR    C
  1060.     JM    NAMC3        ;MATCH IF MINUS
  1061.     LDAX    D        ;GET BYTE OF FCB NAME
  1062.     CPI    '?'
  1063.     JNZ    NAMCY
  1064.     MOV    A,M        ;CHECK NAME FOR NON PRINTABLE CHAR
  1065.     CPI    20H
  1066.     JM    NAMC2
  1067.     CPI    7FH        ;DELETE CODE
  1068.     JP    NAMC2
  1069.     JMP    NAMCX
  1070. NAMCY:    CMP    M        ;COMPARE WITH FILE NAME
  1071.     JNZ    NAMC2
  1072. NAMCX:    INX    H
  1073.     INX    D
  1074.     JMP    NAMC1
  1075. NAMC2:    XRA    A        ;CLEAR CARRY
  1076.     JMP    ENDCK
  1077. NAMC3:    STC
  1078. ENDCK:    POP    B
  1079.     POP    D
  1080.     POP    H
  1081.     JC    TYPCHK        ;MATCH, CHECK TYPE
  1082.     JMP    TAPIN        ;NO MATCH SEARCH SOME MORE
  1083. TYPCHK:    LDA    TYPE        ;GET TYPE
  1084.     CPI    1        ;IS IT TYPE 1
  1085.     JZ    RD1        ;YES,UNBLOCKED RECORD
  1086. ;
  1087. ;    THIS ROUTINE READS BLOCKED TAPES
  1088. ;
  1089. BLKIN:    PUSH    B        ;SAVE BLOCK COUNT
  1090.     MOVE    FILBUF,FCB+1,11    ;MOVE NAME INTO FCB
  1091.     XRA    A
  1092.     STA    FCB+32
  1093.     POP    B        ;RESTORE BLOCK COUNT
  1094.     LXI    H,FILBUF    ;POINTER TO BUFFER
  1095.     MVI    C,128        ;BYTES LEFT IN FIRST BLOCK
  1096. RD5:    CALL    CASR        ;READ A BYTE FROM TAPE
  1097.     MOV    M,A        ;STORE IN BUFFER
  1098.     INX    H        ;INCR BUFFER POINTER
  1099.     DCR    C        ;DECR BYTE COUNT
  1100.     JNZ    RD5        ;BLOCK NOT FINISHED
  1101.     MVI    C,0        ;RESET BYTES PER BLOCK (256)
  1102.     DCR    B        ;DECR BLOCK COUNT
  1103.     JNZ    RD5        ;READ ANOTHER BLOCK
  1104.     SHLD    ENDF        ;SAVE LAST LOCATION USED IN BUFFER
  1105.     XRA    A
  1106.     STA    DISFLG        ;TURN OFF DISPLAY
  1107.     LDA    CKSUM        ;GET CHECKSUM READ FROM TAPE
  1108.     MOV    B,A        ;SAVE IT IN B
  1109.     CALL    CASR        ;READ BLOCK CHECKSUM
  1110.     SUB    B        ;COMPARE
  1111.     JNZ    TPERR        ;CHECKSUM ERROR
  1112. ;
  1113. ;    NOW WRITE THE BLOCK ON DISK OR VERIFY IT
  1114. ;
  1115.     LDA    TYPE        ;GET TYPE
  1116.     ORA    A
  1117.     JNZ    WBLK        ;IF NOT ZERO WRITE BLOCK
  1118.     LDA    VERFLG        ;CHECK VERIFY FLAG (SET IF CKSUM ERROR)
  1119.     ORA    A
  1120.     JNZ    VERBLK        ;VERIFY TAPE
  1121.     $INSTR    IPOINT,120,'VERIFY'    ;VERIFY FILE ?
  1122.     JNC    REN1
  1123.     MVI    A,0FFH
  1124.     STA    VERFLG        ;SET VERIFY FLAG
  1125.     JMP    VERBLK
  1126. REN1:    CALL    RENFIL        ;RENAME FILE ?
  1127.     $INSTR    IPOINT,120,'RUN'    ;RUN FILE ?
  1128.     JC    RUNERR
  1129.     CALL    $$$TYP        ;SAVE OLD TYPE AND SUB $$$
  1130.     DELMAK    FCB        ;IF FIRST BLOCK DELETE
  1131. WD3X:    OPEN    FCB        ;AND OPEN FILE
  1132.     LDA    NBLOCKS        ;NO OF 128 BYTE BLOCKS
  1133.     DCR    A        ;SUBTRACT 1 FOR HEADER
  1134.     STA    NBLOCKS        ;STORE IT BACK
  1135. WBLK:    LDA    VERFLG        ;CHECK VERIFY ONLY
  1136.     ORA    A
  1137.     JNZ    VERNXT
  1138.     LXI    H,FILBUF    
  1139.     SHLD    BPOINT        ;SET DMA ADDR
  1140. WD4:    MOVEI    BPOINT,IPOINT,128    ;MOVE BLOCK
  1141.     WRITE    FCB        ;WRITE A RECORD ON DISK
  1142.     JC    DERR        ;DISK WRITE ERROR (FULL)
  1143.     INDEX    BPOINT,128    ;INCR  ADDR BY 128
  1144.     LDA    NBLOCKS        ;BLOCK COUNT
  1145.     DCR    A
  1146.     STA    NBLOCKS        ;DECR BY 1
  1147.     JNZ    WD4        ;WRITE ANOTHER BLOCK
  1148. WD4X:    LDA    TYPE
  1149.     CPI    2        ;IS IT LAST BLOCK
  1150.     JZ    WD5        ;CLOSE FILE AND EXIT
  1151.     XRA    A
  1152.     STA    CKSUM        ;ZERO CHECKSUB
  1153.     STA    DISFLG        ;TURN OFF DISPLAY
  1154.     MVI    A,10H
  1155.     OUT    CASC        ;RESET RECEIVER
  1156.     CALL    CASR        ;READ DECODE BYTE
  1157.     CALL    CASR        ;READ    TYPE
  1158.     STA    TYPE        ;SAVE IT
  1159.     CALL    CASR        ;READ    LENGTH
  1160.     LXI    H,0
  1161.     MOV    L,A
  1162.     MOV    B,A        ;NO OF 256 BYTE BLOCKS
  1163.     DAD    H
  1164.     SHLD    NBLOCKS        ;SAVE NO OF 128 BYTE BLOCKS
  1165.     LXI    H,FILBUF    ;BUFFER POINTER
  1166.     MVI    C,0        ;NO OF BYTES PER BLOCK (256)
  1167.     MVI    A,0FFH
  1168.     STA    DISFLG        ;TURN ON DISPLAY
  1169.     JMP    RD5        ;READ ANOTHER BLOCK
  1170. WD5:    LDA    AMBIG        ;CHECK AMBIG FILE NAME FLAG
  1171.     ORA    A
  1172.     JNZ    WD6        ;OMIT STOP MESSAGE
  1173.     CALL    STOP        ;DISPLAY STOP TAPE MESSAGE
  1174. WD6:    LDA    VERFLG        ;CHECK VERIFY FLAG
  1175.     ORA    A
  1176.     JNZ    VOUT
  1177.     JMP    DWCLOS
  1178. ;
  1179. ;   WDISK - DISK OUTPUT ROUTINE
  1180. ;
  1181. WDISK:    MOVE    FILBUF,FCB+1,11    ;MOVE NAME INTO FCB
  1182.     LDA    VERFLG
  1183.     ORA    A
  1184.     JNZ    VERIFY
  1185.     $INSTR    IPOINT,120,'VERIFY'    ;VERIFY ONLY?
  1186.     JC    VERIFY
  1187.     $INSTR    IPOINT,120,'RUN'    ;LOAD AND EXEC FILE?
  1188.     JC    RUN
  1189.     LDA    RUNFLG        ;GET RUN FLAG, OTHER RUN TEST
  1190.     ORA    A
  1191.     JNZ    RUN
  1192.     CALL    RENFIL        ;RENAME ?
  1193. WDISK1:    CALL    $$$TYP        ;CHANGE TYPE TO $$$ AND SAVE OLDTYP
  1194.     DELMAK    FCB        ;DELETE AND MAKE FILE
  1195.     OPEN    FCB        ;OPEN THE FILE
  1196.     JC    OPNERR        ;ERROR ON OPEN - PRINT MESS AND EXIT
  1197.     LXI    H,FILBUF+128    ;POINTER TO START OF FILE IN MEMORY
  1198.     SHLD    BPOINT        ;SET POINTER
  1199. DWLOOP:    MOVEI    BPOINT,IPOINT,128    ;MOVE INDIRECT BLOCK TO OUT BUFFER
  1200.     WRITE    FCB        ;WRITE IT OUT
  1201.     JC    DERR        ;JUMP TO WRITE ERROR
  1202.     LHLD    NBLOCKS        ;NO OF BLOCKS TO WRITE
  1203.     DCX    H        ;DECREMENT IT
  1204.     MOV    A,H
  1205.     ORA    L
  1206.     JZ    DWCLOS        ;CLOSE FILE AND EXIT
  1207.     SHLD    NBLOCKS        ;OTHERWISE STORE IT BACK
  1208.     INDEX    BPOINT,128    ;INCR MEMORY POINTER BY 128
  1209.     JMP    DWLOOP        ;BACK TO WRITE ANOTHER BLOCK
  1210. ;
  1211. DWCLOS:    CLOSE    FCB        ;CLOSE FILE
  1212.     MOVE    FCB,FCB+16,12    ;RENAME FILE
  1213.     MOVE    OLDTYP,FCB+25,3
  1214.     MVI    C,19        ;DELETE
  1215.     LXI    D,FCB+16
  1216.     CALL    5
  1217.     MVI    C,23
  1218.     LXI    D,FCB
  1219.     CALL    5        ;RENAME ROUTINE
  1220.     JMP    AMBCHK        ;RETURN FOR MORE TAPE INPUT ON AMBIG NAME
  1221. ;
  1222. ;
  1223. VERIFY:    LXI    H,FILBUF+128    ;POINTER TO START OF TAPE FILE
  1224.     SHLD    BPOINT
  1225.     MVI    A,-1
  1226.     STA    VERFLG        ;SET VERIFY FLAG
  1227.     OPEN    FCB        ;OPEN THE DISK FILE
  1228.     JC    OPNERR        ;PRINT ERROR MESSAGE IF NO FILE
  1229. VLOOP:    READ    FCB        ;READ A DISK RECORD
  1230.     JC    VEND        ;EXIT ON EOF OR ERROR
  1231.     LHLD    BPOINT        ;POINTER FOR COMPARE
  1232.     IMATCH    80H,HL,128    ;COMPARE (HL POINTS TO ONE STRING)
  1233.     JNC    VERERR        ;EXIT IF NO MATCH
  1234.     INDEX    BPOINT,128    ;INCR THE POINTER
  1235.     JMP    VLOOP        ;DO ANOTHER RECORD
  1236. VEND:    CPI    1        ;CHECK END FILE
  1237.     JNZ    RDERR        ;READ ERROR IF NOT 1
  1238. VOUT:    PRINT    BELL2
  1239.     PRINTL    'VERIFIED SUCCESSFULLY$'
  1240.     PRINT    CRLF
  1241. AMBCHK:    LDA    AMBIG        ;CONTINUE IF AMBIGUOUS FILE NAME
  1242.     ORA    A
  1243.     JZ    MOREIN        ;EXIT
  1244.     MOVE    AMBNAM,FCB,12    ;REPLACE AMBIG NAME IN FCB
  1245.     XRA    A
  1246.     STA    FCB+12        ;ZERO EXTENTS
  1247.     STA    FCB+32
  1248.     JMP    TAPIN        ;BACK TO TAPE INPUT
  1249. ;
  1250. ;    THIS SECTION MOVES THE FILE TO 100H AND EXECUTES IT. A CHECK IS
  1251. ;    MADE TO VERIFY THAT IT IS A COM FILE.
  1252. ;
  1253. RUN:    $MATCH    65H,'COM'    ;TYPE IN FCB
  1254.     JNC    TYPERR
  1255.     MOVE    CODE,80H,40    ;FILE OVERLAYS PROG MOVE TO BUFFER
  1256.     JMP    80H        ;GO EXECUTE MOVE ROUTINE
  1257. CODE:    LXI    B,100H
  1258.     LXI    D,FILBUF+128    ;POINTS TO BEGINNING OF FILE
  1259.     LHLD    ENDF        ;LAST LOC TO BE MOVED
  1260. MLOOP:    LDAX    D        ;GET A BYTE
  1261.     STAX    B        ;STORE IT
  1262.     INX    D
  1263.     INX    B
  1264.     MOV    A,H        ;COMPARE DE WITH HL
  1265.     CMP    D
  1266.     JNZ    89H
  1267.     MOV    A,L
  1268.     CMP    E
  1269.     JNZ    89H
  1270.     LXI    H,0
  1271.     SHLD    80H        ;ZERO START OF INPUT BUFFER
  1272.     JMP    100H        ;EXECUTE MOVED FILE
  1273. ;
  1274. ;    RENAME ROUTINE - RENAME FILE FOR TAPE TO DISK TRANSFER
  1275. ;
  1276. RENFIL:    $INSTR    IPOINT,120,'RENAME'    ;RENAME ?
  1277.     RNC            ;RETURN IF NO 'RENAME'
  1278. SKPBLK:    INX    H        ;INCR POINTER
  1279.     MOV    A,M        ;GET A BYTE
  1280.     CPI    20H        ;IS IT A BLANK
  1281.     JZ    SKPBLK        ;SKIP OVER BLANKS
  1282.     SHLD    SLOC2        ;STORE POINTER
  1283.     FILFCB    FCB,SLOC2    ;FILL IN FCB WITH NEW NAME
  1284.     JC    NAMERR        ;ERROR IN NAME (TOO LONG)
  1285.     RET
  1286. ;
  1287. ;    VERIFY BLOCKED TAPE
  1288. ;
  1289. VERBLK:    OPEN    FCB        ;OPEN THE FILE
  1290.     JC    OPNERR        ;EXIT IF NO FILE
  1291. VERNXT:    LXI    H,FILBUF+1024    ;POINTER FOR DISK INPUT
  1292.     SHLD    BPOINT
  1293.     LDA    NBLOCKS
  1294.     CPI    9        ;SET BLOCKS TO 8 IF > 8
  1295.     JM    VER2
  1296.     MVI    A,8        ;SET BLOCKS TO 8
  1297.     STA    NBLOCKS
  1298. VER2:    READ    FCB        ;READ A RECORD
  1299.     JNC    VER3
  1300.     CPI    1        ;TEST EOF
  1301.     JNZ    RDERR        ;DISK READ ERROR
  1302.     JMP    WD5        ;PRINT STOP MESSAGE AND EXIT
  1303. VER3:    MOVEI    IPOINT,BPOINT,128
  1304.     INDEX    BPOINT,128    ;INCR POINTER
  1305.     LDA    NBLOCKS        ;BLOCK COUNT
  1306.     DCR    A
  1307.     STA    NBLOCKS        ;DECR COUNT BY 1
  1308.     JNZ    VER2        ;READ SOME MORE
  1309.     LHLD    BPOINT        ;POINTS TO END OF BLOCK
  1310.     DCX    H        ;DECR BY 1
  1311.     XCHG            ;TO DE
  1312.     LXI    H,FILBUF+1024    ;POINTS TO DISK DATA
  1313.     LXI    B,FILBUF    ;POINTS TO TAPE DATA
  1314. VER4:    LDAX    B        ;GET A BYTE
  1315.     CMP    M        ;COMPARE
  1316.     JNZ    VERERR        ;ERROR, NO MATCH
  1317.     INX    H
  1318.     INX    B
  1319.     CPHL            ;COMPARE HL AND DE
  1320.     JNZ    VER4
  1321.     JMP    WD4X        ;BACK INTO TAPE INPUT ROUTINE
  1322. ;
  1323. ;    THIS ROUTINE SCANS FCB NAME AND FILLS * TO ?.
  1324. ;    CARRY SET SET IF * OR ? IN FILE NAME
  1325. ;
  1326. SCANFCB:LXI    H,FCB+1        ;POINTS TO FILE NAME
  1327.     MVI    B,'?'
  1328.     MVI    A,'*'
  1329.     CMP    M        ;IS NAME *
  1330.     JNZ    SCAN2
  1331.     MVI    C,8        ;FILL IN 8 '?'
  1332. SCAN1:    MOV    M,B        ;MOVE A BYTE
  1333.     INX    H
  1334.     DCR    C
  1335.     JNZ    SCAN1
  1336. SCAN2:    LXI    H,FCB+9        ;POINTS TO TYPE
  1337.     CMP    M        ;IS TYPE A *
  1338.     JNZ    SCAN4
  1339.     MVI    C,3        ;FILL TYPE WITH '?'
  1340. SCAN3:    MOV    M,B        ;MOVE A BYTE
  1341.     INX    H
  1342.     DCR    C
  1343.     JNZ    SCAN3
  1344. SCAN4:    LXI    H,FCB+1        ;RESCAN FOR ? AND SET CARRY
  1345.     MVI    C,11
  1346.     MOV    A,B        ;PUT '?' IN A
  1347. SCAN5:    CMP    M
  1348.     JZ    SCAN6
  1349.     INX    H
  1350.     DCR    C
  1351.     JNZ    SCAN5
  1352.     XRA    A        ;CARRY OFF NO '?'
  1353.     RET
  1354. SCAN6:    STC            ;CARRY ON
  1355.     RET
  1356. ;
  1357. ;    THIS ROUTINE SEARCHES DIRECTORY WITH AMBIGUOUS FILE NAME
  1358. ;
  1359. GETNAM:    MVI    A,0
  1360.     STA    FCB+12        ;SET FILE EXTENT TO ZERO
  1361.     SEARCH    FCB
  1362.     CPI    0FFH        ;CHECK NAME NOT PRESENT
  1363.     JZ    OPNERR        ;DISPLAY ERROR MESSAGE
  1364.     JMP    N1
  1365. GETNEXT:SERNXT    FCB        ;SEARCH FOR NEXT OCCURRANCE OF NAME
  1366.     CPI    0FFH        ;NAME NOT FOUND ?
  1367.     JNZ    N1        ;RETURN ADDR IF FOUND
  1368.     STC
  1369.     RET            ;SET CARRY AND RETURN
  1370. N1:    ANI    03        ;ADDR MOD 4
  1371.     RRC
  1372.     RRC
  1373.     RRC            ;ADDR * 32
  1374.     ADI    80H        ;ADD BASE ADDR 
  1375.     LXI    H,0
  1376.     MOV    L,A        ;HL NOW POINTS TO FCB FROM DIR
  1377.     XRA    A        ;CLEAR CARRY
  1378.     RET
  1379. ;
  1380. ;   WRITE SYNC STREAM ON TAPE (65K BYTES)
  1381. ;
  1382. SYNC:    CALL    STARTW        ;PRINT START MESSAGE
  1383.     MVI    A,0FFH
  1384.     STA    DISFLG        ;TURN ON DISPLAY
  1385.     LXI    D,0        ;SYNC BYTE COUNTER
  1386. SYNC1:    MVI    A,0E6H        ;LOAD A SYNC BYTE
  1387.     CALL    CASW        ;WRITE IT OUT
  1388.     DCX    D        ;DECR COUNT
  1389.     MOV    A,D
  1390.     ORA    E
  1391.     JNZ    SYNC1        ;TEST COUNT AND LOOP
  1392.     CALL    STOP        ;PRINT STOP MESSAGE
  1393.     JMP    MOREIN
  1394. ;
  1395. ;
  1396. ;    SWAP FCB TYPE WITH $$$
  1397. ;
  1398. $$$TYP:    MOVE    FCBTYP,OLDTYP,3    ;MOVE TYPE TO TEMPORARY STORAGE
  1399.     FILL    FCBTYP,FCBTYP+2,'$'
  1400.     RET
  1401. ;
  1402. ;    WRITE LEADER AND ID BLOCK OF 100 76H BYTES ON TAPE
  1403. ;
  1404. WRID:    LXI    D,1500        ;LOAD COUNT
  1405. WRHD:    MVI    A,3CH        ;START BYTE
  1406.     CALL    CASW        ;WRITE IT
  1407.     DCX    D        ;DECR COUNT
  1408.     MOV    A,D
  1409.     ORA    E
  1410.     JNZ    WRHD        ;LOOP TILL ZERO
  1411.     MVI    D,100        ;LOAD COUNT
  1412.     MVI    A,0E6H        ;SYNC BYTE
  1413.     CALL    CASW        ;WRITE IT
  1414. WRID1:    MVI    A,76H        ;HALT CODE
  1415.     CALL    CASW        ;WRITE IT
  1416.     DCR    D
  1417.     JNZ    WRID1        ;WRITE ANOTHER BYTE
  1418.     RET
  1419. ;
  1420. ;    SEARCH FOR BLOCK OF 100 76H BYTES ON TAPE
  1421. ;
  1422. RDID:    MVI    D,100        ;LOAD COUNT
  1423.     MVI    A,10H
  1424.     OUT    CASC        ;RESET RECEIVER
  1425. RDID1:    CALL    CASR        ;READ A BYTE
  1426.     CPI    76H        ;COMPARE WITH 76H
  1427.     JNZ    RDID        ;START OVER
  1428.     DCR    D        ;DECR COUNT
  1429.     JNZ    RDID1        ;READ ANOTHER BYTE
  1430.     RET
  1431. ;
  1432. ;
  1433. ;
  1434. ;   WRITE SPACER BLOCK OF START BYTES FOR BLOCKED TAPES
  1435. ;
  1436. WRSPAC:    PUSH    H
  1437.     PUSH    D
  1438.     PUSH    B
  1439.     LXI    D,160        ;COUNT
  1440. WRSP1:    MVI    A,3CH        ;START BYTE
  1441.     CALL    CASW        ;WRITE IT
  1442.     DCX    D        ;DECR COUNT
  1443.     MOV    A,D
  1444.     ORA    E
  1445.     JNZ    WRSP1        ;LOOP TILL COUNT IS ZERO
  1446.     POP    B
  1447.     POP    D
  1448.     POP    H
  1449.     RET
  1450. ;
  1451. ;   CONSOLE MESSAGE ROUTINES
  1452. ;
  1453. STARTW:    PRINT    CRLF2
  1454.     PRINTL    'START CASSETTE TAPE <<RECORD>> - TYPE CARRIAGE RETURN$'
  1455.     PRINT    CRLF2
  1456.     CONIN
  1457.     CPI    3        ;ESCAPE CHARACTER
  1458.     JZ    GETOUT
  1459.     RET
  1460. GETOUT:    POP    PSW        ;RESET STACK POINTER
  1461.     JMP    MOREIN        ;BACK FOR MORE INPUT
  1462. STOP:    PRINT    BELL2
  1463.     PRINTL    'STOP CASSETTE TAPE$'
  1464.     PRINT    CRLF
  1465.     RET
  1466. ;
  1467. ;
  1468. ;   EXIT AND ERROR ROUTINES
  1469. ;
  1470. VERERR:    PRINT    BELL2
  1471.     PRINTL    'VERIFY ERROR$'
  1472.     JMP    MOREIN
  1473. ;
  1474. TYPERR:    PRINT    BELL2
  1475.     PRINTL    'ERROR - FILE TYPE NOT <COM> - CANNOT BE RUN$'
  1476.     JMP    MOREIN
  1477. ;
  1478. RUNERR:    PRINT    CRLF2
  1479.     PRINTL 'ERROR - A PROGRAM CAN NOT BE RUN FROM A BLOCKED TAPE$'
  1480.     PRINT    CRLF
  1481.     PRINTL    'TO EXECUTE PROGRAM FIRST LOAD TO DISK$'
  1482.     CALL    STOP        ;DISPLAY STOP TAPE MESSAGE
  1483.     JMP    MOREIN
  1484. ;
  1485. DERR:    PRINT    BELL2
  1486.     PRINTL    'DISK WRITE ERROR - DISK OR DIRECTORY FULL$'
  1487.     PRINT    CRLF
  1488.     PRINTL    'FILE DELETED FROM DISK$'
  1489.     DELETE    FCB
  1490. ;
  1491. MOREIN:    LDA    INFLAG
  1492.     ORA    A
  1493.     JNZ    NEWIN
  1494. ;
  1495. MONITOR: PRINT    CRLF
  1496.     RESDRV    DRVNO        ;RESTORE ORIGINAL DRIVE NUMBER
  1497.     JMP    0        ;EXIT BACK TO MONITOR
  1498. ;
  1499. ;
  1500. ;   DATA ALLOCATIONS -
  1501. ;
  1502. FCB    =    5CH    ;FILE CONTROL BLOCK
  1503. FCBNAM    =    FCB+1    ;FILE NAME
  1504. FCBTYP    =    FCB+9    ;FILE TYPE
  1505. BELL:    .ASCII    [07H][0DH][0AH][24H]
  1506. BELL2:    .ASCII    [07H][0DH][0AH][0AH][24H]
  1507. CRLF:    .ASCII    [0DH][0AH]'$'
  1508. CRLF2:    .ASCII    [0DH][0AH][0AH][24H]
  1509. BCOUNT:    .BYTE    65    ;COUNT OF BYTES PER LINE
  1510. RUNFLG:    .BYTE    0    ;CONTROLS FILE TO BE LOADED AND EXECUTED
  1511. DISFLG:    .BYTE    0    ;CONTROLS DISPLAY DURING TAPE OPERATIONS
  1512. DRVNO:    .BYTE    0    ;CURRENTLY LOGGED DISK DRIVE NO
  1513. NEWDRV:    .BYTE    0    ;STORAGE FOR NEW DRIVE NO IF ONE IS SELECTED
  1514. CKSUM:    .BYTE    0    ;STORAGE FOR TAPE CHECKSUM
  1515. INFLAG:    .BYTE    0    ;FLAG - IF SET RETURN FOR MORE CONSOLE INPUT
  1516. FIRST:    .BYTE    0    ;INDICATES FIRST RECORD OF BLOCKED TAPE
  1517. BLOCK:    .BYTE    0    ;BLOCK COUNT FOR BLOCKED TAPE
  1518. TYPE:    .BYTE    0    ;TYPE CODE FOR BLOCKED TAPE
  1519. LENGTH:    .BYTE    0    ;LENGTH OF BLOCKED RECORD 256 BYTE BLOCKS
  1520. DFLAG1:    .BYTE    0    ;DISPLAY OFF FOR SLOW TERMINALS
  1521. VERFLG:    .BYTE    0    ;FLAG - SET FOR VERIFICATION
  1522. AMBIG:    .BYTE    0    ;AMBIGUOUS NAME FLAG
  1523. FAMBIG:    .BYTE    0    ;FIRST AMBIGUOUS FILE FLAG
  1524. BLKBLK:    .BYTE    0    ;BLOCK COUNT FOR BLOCKED TAPES
  1525. MEMEND:    .WORD    0    ;END MEMORY FOR FILE STORAGE
  1526. BPOINT:    .WORD    0    ;POINTER TO FILE MEMORY BUFFER
  1527. SLOC2:    .WORD    0    ;STORAGE FOR POINTER TO FCB NAME
  1528. SLOC1:    .WORD    88H    ;POINTER TO NAME IN INPUT BUFFER
  1529. IPOINT:    .WORD    80H    ;POINTER TO DISK INPUT BUFFER
  1530. NBLOCKS:.WORD    0    ;NUMBER OF 256 BYTE BLOCKS IN FILE
  1531. ENDF:    .WORD    0    ;LAST MEMORY LOC USED TO STORE FILE
  1532. OLDTYP:    .BLKB    3    ;TEMP STORAGE FOR FILE TYPE (FOR RENAME)
  1533. AMBNAM:    .BLKB    12    ;STORAGE FOR AMBIGUOUS FILE NAME
  1534. ENDSTK:    .BLKW    16    ;NEW STACK
  1535. NEWSTK:    .WORD    0    ;START OF NEW STACK
  1536. FILBUF:    .WORD    0    ;FILE BUFFER - TO TOP OF MEMORY
  1537.     .END
  1538.