home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol042 / mtx.asm < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  35.8 KB  |  1,556 lines

  1. ;===================================================================
  2. ;    MICRO RESOURCES CP/M -- MTX FILE TRANSFER PROGRAM
  3. ;        FOR USE WITH ICOM 3812 DD CP/M 1.4
  4. ;===================================================================
  5. ;
  6. ;
  7. ; THIS PROGRAM IS A UTILITY TO TRANSFER FILES FROM PCC 2000 MTX
  8. ; DOUBLE DENSITY DISKS TO CP/M DISKS OR TO TRANSFER A CP/M
  9. ; FILE TO A PCC 2000 MTX DOUBLE DENSITY DISK. A PROVISION HAS
  10. ; ALSO BEEN INCLUDED TO ALLOW EXAMINATION OF THE DIRECTORY OF
  11. ; THE MTX DISKETTE. THE OPERATION OF THIS PROGRAM ASSUMES
  12. ; THAT A CP/M SYSTEM DISK IS PRESENT IN DRIVE A: AND THAT THE
  13. ; MTX DATA DISK IS IN DRIVE B:. THE BIOS PRIMITIVES OF THE CP/M
  14. ; SYSTEM ARE ACCESSED DIRECTLY TO ALLOW READING AND WRITING
  15. ; OF THE DOUBLE DENSITY MTX DISK WITH IT'S 2 TO 1 LOGICAL
  16. ; TO PHYSICAL SECTOR MAPPING. NOTE THAT THIS SOFTWARE IS
  17. ; SPECIFICALLY TAYLORED TO FUNCTION THROUGH THE BIOS VECTORS
  18. ; OF THE LIFEBOAT IMPLEMENTATION OF CP/M 1.4 ON AN ICOM 3812
  19. ; DOUBLE DENSITY DISK SYSTEM.
  20. ;
  21. ; THIS PROGRAM DOES NOT PACK THE FILES OF THE MTX DISK
  22. ; WHEN CREATING NEW FILES UPON TRANSFER FROM A CP/M FILE.
  23. ; SUBSEQUENT PACKING MAY DONE UPON THE DESTINATION MTX/PCC 2000
  24. ; SYSTEM.
  25. ;
  26. ; THE DIRECTORIES OF EITHER DISK WILL BE SCANNED FOR FILES
  27. ; OF SIMILAR NAMES BEFORE A TRANSFER IS ACTUALLY MADE. A PROMPT
  28. ; QUESTION WILL INDICATE WHEN THE FILE ALREADY EXISTS. IN THE
  29. ; CASE OF THE CP/M DISK THE INDICATED FILE MAY BE ERASED IF
  30. ; DESIRED. WITH THE MTX DISK A FILE WILL NOT BE DELETED
  31. ; AND THE NAME OF THE SOURCE FILE ON THE CP/M DISK WILL HAVE
  32. ; TO BE CHANGED TO A NAME NOT CURRENTLY ON THE MTX DISK.
  33. ; FILE NAMES OF MTX FILES ARE A MAXIMUM OF 6 ASCII CHARACTERS
  34. ; IN LENGTH SO THE CP/M FILE TRANSFERRED TO THE MTX DISK
  35. ; WILL HAVE ITS NAME TRUNCATED TO THE FIRST SIX CHARACTERS.
  36. ; THE MTX FILE TYPE WILL ALWAYS BE SET TO 00 AS AN INDEXED
  37. ; FILE TYPE. RECORD SIZE OF A MTX DESTINATION FILE WILL BE
  38. ; SET TO 128 BYTES. FOR MTX DESTINATION FILES THAT ARE AN
  39. ; ODD NUMBER OF 128 BYTE RECORDS THE LAST HALF IS BACK
  40. ; FILLED WITH AN ARBITRARY CHOICE OF ZEROS.
  41. ;
  42. ; FOR FILES TRANSFERRED TO CP/M FROM MTX DISKS THE FILE
  43. ; TYPE WILL BE CHECKED AND IF THE SOURCE TYPE IS NOT AN
  44. ; INDEXED FILE THEN THE TRANSFER TO CP/M WILL NOT BE
  45. ; MADE.
  46. ;
  47. ; THIS PROGRAM BUFFERS CP/M SECTOR READS UP 156 IN 
  48. ; LENGTH TO MAKE THE TRANSFER MORE EFFICIENT.
  49. ;
  50. ;
  51. ;
  52. ;
  53. ;*****************************************************************
  54. ;
  55. ;THIS SOFTWARE IS PROTECTED UNDER THE FOLLOWING COPYRIGHT
  56. ;AND MAY NOT BE REPRODUCED OR COPIED IN ANY FORM WITHOUT 
  57. ;SPECIFIC PERMISSION FROM MICRO RESOURCES.
  58. ;
  59. ;
  60. ;   COPYRIGHT (C) 1980
  61. ;
  62. ;
  63. ;    MICRO RESOURCES
  64. ;    MICHAEL J. KARAS
  65. ;    2468 HANSEN CT.
  66. ;    SIMI VALLEY, CA 93065
  67. ;    (805) 527-7922
  68. ;
  69. ;ANY QUESTIONS ABOUT THIS PROGRAM OR ITS APPLICATION
  70. ;CAN BE DIRECTED TO THE ABOVE ADDRESS OR TELEPHONE NUMBER.
  71. ;
  72. ;*********************************************************************
  73. ;
  74. WBOOT    EQU    00        ;CP/M WARM BOOT ENTRY ADDRESS
  75. ;
  76. ERRLIM    EQU    10        ;MAX ALLOWABLE ERRORS
  77. ;DEFINE ASCII CHARACTERS USED
  78. ;
  79. LF    EQU    10        ;LINEFEED
  80. CR    EQU    13        ;CARRIAGE RETURN
  81. ;
  82. ;START OF EXECUTABLE CODE
  83. ;
  84.     ORG    100H
  85.     CALL    START        ;GO PRINT ID
  86.     DB    'MICRO RESOURCES FILE TRANSFER UTILITY '
  87.     DB    CR,LF,' ICOM 3812 CP/M <----> PCC 2000 MTX'
  88.     DB    CR,LF,'          VER 1.1 11/7/80'
  89.     DB    CR,LF,'$'
  90. ;
  91.     DB    'COPYRIGHT 1980 MICRO RESOURCES'
  92.     DB    '2468 HANSEN CT.'
  93.     DB    'SIMI VALLEY, CA 93065'
  94.     DB    '(805) 527-7922'
  95. START:
  96.     POP    D        ;GET ID MESSAGE
  97.     MVI    C,PRINT
  98.     CALL    BDOS        ;PRINT ID MESSAGE
  99. ;
  100. ;INIT PRIVATE STACK
  101. ;
  102.     LXI    H,0        ;HL=0
  103.     DAD    SP        ;HL=STACK FROM CP/M
  104.     SHLD    STACK        ;..SAVE IT
  105.     LXI    SP,STACK     ;SP=MY STACK
  106. ;
  107. ;INITIALIZE THE CP/M FILE BUFFERING PARAMETERS
  108. ;
  109.     MVI    A,00H
  110.     STA    SECINBF        ;ZERO SEC IN BUFFER COUNTER
  111.     STA    EOFLG        ;RESET CP/M END OF FILE FLAG
  112.     LXI    H,DBUF        ;INITIALIZE BUFFER POINTER
  113.     SHLD    SECPTR
  114. ;
  115. ;INITIALIZE THE JMPS TO CP/M BIOS
  116. ;
  117.     CALL    INITADR
  118. ;
  119. ;SAVE PROGRAM OPTION
  120. ;
  121.     CALL    PROCOPT
  122. ;
  123. ;MOVE THE FILENAME FROM FCB 2 TO FCB 1
  124. ;
  125.     CALL    MOVEFCB
  126. ;
  127. ;JMP TO APPROPRIATE FUNCTION
  128. ;
  129.     LDA    OPTION        ;GET PROGRAM OPTION
  130. ;
  131.     CPI    'R'        ;READ MTX FILE?
  132.     JZ    MTXRD
  133. ;
  134.     CPI    'W'        ;WRITE MTX FILE?
  135.     JZ    MTXWR
  136. ;
  137.     CPI    'D'         ;LOOK AT MTX DIRECTORY
  138.     JZ    MTXDIR
  139. ;
  140.     CPI    'H'        ;GO TO HELP FILE PRINTOUT?
  141.     JZ    HELP
  142. ;
  143. ;INVALID OPTION
  144. ;
  145.     JMP    BADOPT
  146. ;
  147. ;
  148. ;
  149. * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  150. *                                        *
  151. *    MTXDIR: LISTS MTX DIRECTORY TO CONSOLE          *
  152. *                                   *
  153. * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  154. ;
  155. ;
  156. ;THE DIRECTORY OF THE DOUBLE DENSITY MTX
  157. ;DISK IN DRIVE B: IS LISTED TO THE CONSOLE IN
  158. ;A SINGLE COLUMN FORMAT. CONSOLE I/O IS DONE
  159. ;THROUGH CP/M SO THAT THE CTL-S AND CTL-P
  160. ;FUNCTIONS WILL WORK. THE LISTING ALSO STOPS
  161. ;AFTER EACH 16 ENTRIES HAVE BEEN TYPED
  162. ;
  163. MTXDIR:
  164.     CALL    ILPRT        ;PRINT THE DIRECTORY HEADER LABEL
  165.     DB    CR,LF,CR,LF,'            MTX DISK DIRECTORY'
  166.     DB    CR,LF,CR,LF
  167.     DB    'FILENAME  TYPE RECORD RECORD START  END ',CR,LF
  168.     DB    '               COUNT  SIZE   SECTOR SECTOR',CR,LF
  169.     DB    '------------------------------------------',CR,LF,0
  170. ;
  171.     MVI    A,016        ;SET PRINT LOOP COUNT
  172.     STA    LISTCNT
  173.     MVI    A,00        ;SET SCAN FOR FIRST ENTRY
  174.     JMP    MDIR2        ;JUMP INTO LOOP
  175. MDIR1:
  176.     MVI    A,01        ;SET SCAN CODE FOR NEXT ENTRY
  177. MDIR2:
  178.     CALL    MDIRSC        ;SCAN FOR NEXT DIRECTORY ENTRY
  179.     ORA    A        ;SET FLAGES FOR RETURN CODE
  180.     JNZ    MDEREX        ;GO EXIT FOR FULL DISK DIRECTORY
  181.     LDA    MDENT        ;GET FIRST CHAR OF DERECTORY ENTRY
  182.     CPI    0FFH        ;MUST BE AT END OF THE LIST
  183.     JZ    MDIREX
  184.     CPI    000H        ;CHECK IF THIS ENTRY IS EMPTY
  185.     JZ    MDIR1        ;SKIP PRINT IF SO
  186.     CALL    PRTDIR        ;PRINT THIS ENTRY
  187. ;
  188.     LDA    LISTCNT        ;GET LIST LINE COUNT
  189.     DCR    A        ;DECREMENT IT
  190.     STA    LISTCNT        ;STORE NEW COUNT BACK
  191.     JNZ    MDIR1        ;GO TO DO NEXT ENTRY
  192. ;
  193.     CALL    ILPRT        ;GIVE THE GUY A CHANCE TO STOP A LONG DIRECTORY
  194.     DB    1,CR,LF,0
  195. ;
  196.     MVI    A,016        ;RESET PRINT LOOP COUNT
  197.     STA    LISTCNT
  198.     JMP    MDIR1        ;GO START ON 16 MORE ENTRIES
  199. ;
  200. MDIREX:
  201.     CALL    ILPRT        ;PRINT END OF LIST MESSAGE
  202.     DB    CR,LF,CR,LF,'END OF MTX DISK DIRECTORY',CR,LF,0
  203. MDIREX1:
  204.     MVI    C,00H        ;RESTORE SELECT OF DRIVE A:
  205.     CALL    SELDSK        ;DIRECT BIOS ACCESS
  206.     JMP    EXIT        ;DONE WITH DIRECTORY
  207. ;
  208. MDEREX:
  209.     CALL    ILPRT        ;PRINT DISK FULL MESSAGE
  210.     DB    CR,LF,'++MTX DISK DIRECTORY SPACE FULL++',CR,LF,0
  211. ;
  212.     JMP    MDIREX1
  213. ;
  214. ;
  215. ;
  216. ;
  217. ;SCAN MTX DIRECTORY ROUTINE
  218. ;    ROUTINE ENTRY IS CODED TO ALLOW VARIABLE FUNCTIONS
  219. ;    CODE IS PASSED IN THE A REGISTER
  220. ;    CODES AS FOLLOWS:
  221. ;        00=OPEN SCAN FROM BEGINNING WITH LOGICAL SECTOR 1
  222. ;        01=GET NEXT DIRECTORY ENTRY
  223. ;
  224. ;    RETURN VALUE IS THE FIRST OR NEXT ENTRY AS SPECIFIED BY THE
  225. ;    FUNCTION CODE AND IS PASSED IN BUFFER "MDENT" WHICH IS 16
  226. ;    BYTES LONG.
  227. ;
  228. ;    THIS ROUTINE SCANS AND RETURNS ALL POSSIBLE ENTRIES
  229. ;    AND WHEN END OF LOGICAL SECTOR 25 IS ENCOUNTERED AN 
  230. ;    0FFH CODE IS RETURNED IN THE ACCUMULATOR. ELSE A 00H 
  231. ;    CODE IS RETURNED.
  232. ;
  233. ;
  234. ;
  235. MDIRSC:
  236.     ORA    A        ;SET FLAGS FOR FUNCTION CHECK
  237.     JNZ    NEXTENT        ;FOR NON-ZERO CODE JUST GET NEXT ENTRY
  238. ;
  239. ;SETUP FOR BEGINNING OF SCAN
  240.     MVI    A,000H        ;SETUP START SECTOR OF DIRECTORY-1 
  241.     STA    MDIRSEC
  242.     MVI    A,016        ;SET CURRENT SUBSCAN COUNT TO MAX
  243.     STA    DIRSECI
  244. ;
  245. NEXTENT:
  246.     LDA    DIRSECI        ;GET SECTOR INDEX
  247.     CPI    016        ;AT MAXIMUM ENTRY?
  248.     JNZ    SAMSEC        ;NO STAY WITH THIS SECTOR
  249.     LXI    H,MDIRSEC
  250.     INR    M        ;INCREMENT CURRENT SECTOR NUMBER
  251.     MOV    A,M        ;GET THE SECTOR NUMBER
  252.     CPI    026        ;CHECK FOR THE LAST SECTOR
  253.     JNZ    NXTSEC        ;GO AROUND THE END OF TRACK EXIT
  254. ;
  255.     MVI    A,0FFH        ;SETUP EXIT FOR END OF DIRECTORY SPACE
  256.     RET
  257. ;
  258. NXTSEC:
  259.     MOV    L,A
  260.     MVI    H,00H
  261.     CALL    MRDSEC        ;GO READ MTX SECTOR
  262.     LXI    H,MTXBUF    ;MOVE INPUT BUFFER 
  263.     LXI    D,DIRBUF    ;..TO DIRECTORY BUFFER
  264.     MVI    B,00H        ;SET COUNT FOR FULL 256
  265.     CALL    MOVE
  266.     MVI    A,00
  267.     STA    DIRSECI        ;SET SECTOR INDEX TO MINIMUM
  268. ;
  269. SAMSEC:
  270.     LXI    H,DIRSECI
  271.     MOV    B,M        ;GET THE INDEX
  272.     INR    M        ;INCR THE SECTOR INDEX
  273.     LXI    H,DIRBUF    ;POINT TO THE MTX DIRECTORY BUFFER
  274.     LXI    D,016        ;LENGTH OF AN ENTRY
  275.     MOV    A,B
  276.     CPI    00H        ;CHECK FOR ILLEGAL ZERO LOOP COUNT
  277.     JZ    SAMSEC2
  278. SAMSEC1:
  279.     DAD    D        ;LOOP TO MAKE OFFSET INDEX
  280.     DCR    B
  281.     JNZ    SAMSEC1
  282. SAMSEC2:
  283.     LXI    D,MDENT        ;POINT TO ENTRY PASS BUFFER
  284.     MVI    B,016        ;SETUP LENGTH OF DIRECTORY ENTRY
  285.     CALL    MOVE        ;GO MOVE A DIRECTORY ENTRY
  286.     LXI    H,MDENT        ;SETUP TO STRIP MTX MBS'S FROM FILE NAME
  287.     MOV    A,M        ;SEE IF FIRST BYTE IS 0FFH
  288.     CPI    0FFH        ;IF SO WE SKIP MSB STRIP
  289.     JZ    ENDRET
  290.     MVI    B,06H        ;CHARACTER COUNT
  291. SAMSEC3:
  292.     MOV    A,M        ;GET CHARACTER OF NAME
  293.     ANI    07FH        ;STRIP MTX STRING CRAP
  294.     MOV    M,A
  295.     INX    H
  296.     DCR    B        ;DEC NAME BYTE COUNT
  297.     JNZ    SAMSEC3
  298. ;
  299. ENDRET:
  300.     MVI    A,00H        ;SET NORMAL RETURN FLAG
  301.     RET
  302. ;
  303. ;
  304. ;
  305. ;
  306. ;DIRECTORY SCAN POINTER PARAMETERS
  307. ;
  308. ;
  309. MDIRSEC    DB    00        ;CURRENT DIRECTORY SECTOR NUMBER
  310. DIRSECI    DB    00        ;INDEX OF SCAN INTO CURRENT DIRECTORY SECTOR
  311. DIRBUF    DS    256        ;256 BYTE DIRECTORY ENTRY BUFFER
  312. LISTCNT    DB    00        ;DIRECTORY LIST ENTRY COUNT
  313. ;
  314. ;
  315. ;
  316. ;PRINT DIRECTORY ENTRY SUBROUTINE
  317. ;
  318. ;
  319. PRTDIR:
  320.     LXI    H,MDENT        ;POINT TO DIRECTORY ENTRY BUFFER
  321.     MVI    A,'B'
  322.     CALL    CTYPE        ;PRINT OUT DRIVE DESIGNATOR
  323.     MVI    A,':'
  324.     CALL    CTYPE
  325.     MVI    B,06        ;FILE NAME CHARACTER COUNT
  326. NAMLP:
  327.     MOV    A,M        ;GET NAME CHARACTER
  328.     CALL    CTYPE
  329.     INX    H        ;INCREMENT BUFFER POINTER
  330.     DCR    B
  331.     JNZ    NAMLP        ;GO FOR NEXT NAME CHAR
  332. ;
  333.     CALL    SP3        ;THREE SPACES
  334.     MOV    A,M        ;GET TYPE BYTE
  335.     CALL    HEXO        ;SHOW IT
  336.     INX    H        ;INCREMENT THE BUFFER POINTER
  337. ;
  338.     INX    H        ;SKIP THE KEY SIZE FIELD
  339. ;
  340.     CALL    SP2        ;TWO SPACES
  341.     MOV    D,M        ;GET HIGH RECORD COUNT BYTE
  342.     INX    H
  343.     MOV    E,M        ;GET LOW RECORD COUNT BYTE
  344.     INX    H
  345.     PUSH    H        ;SAVE STRING POINTER
  346.     CALL    DECPRT        ;GO PRINT RECORD COUNT
  347.     POP    H
  348. ;
  349.     CALL    SP2        ;TWO SPACES
  350.     MOV    D,M        ;GET HIGH RECORD SIZE BYTE
  351.     INX    H
  352.     MOV    E,M        ;GET LOW RECORD SIZE BYTE
  353.     INX    H
  354.     PUSH    H        ;SAVE STRING POINTER
  355.     CALL    DECPRT        ;GO PRINT RECORD SIZE
  356.     POP    H
  357. ;
  358.     CALL    SP2        ;TWO SPACES
  359.     MOV    D,M        ;GET HIGH START SECTOR BYTE
  360.     INX    H
  361.     MOV    E,M        ;GET LOW START SECTOR BYTE
  362.     INX    H
  363.     PUSH    H        ;SAVE STRING POINTER
  364.     CALL    DECPRT        ;GO PRINT START SECTOR COUNT
  365.     POP    H
  366. ;
  367.     CALL    SP2        ;TWO SPACES
  368.     MOV    D,M        ;GET HIGH END SECTOR BYTE
  369.     INX    H
  370.     MOV    E,M        ;GET LOW END SECTOR BYTE
  371.     DCX    D        ;SET THE ENDING SECTOR TO REAL VALUE
  372.     CALL    DECPRT        ;GO PRINT ENDING SECTOR COUNT
  373. ;
  374.     CALL    CRLF        ;GET READY FOR NEXT LINE
  375.     RET
  376. ;
  377. ;
  378. ;CONVERT AND PRINT A TWO BYTE VALUE AT CONSOLE IN DECIMAL
  379. ;
  380. DECPRT:
  381.     XCHG            ;HL=WORD TO PRINT
  382.     LXI    D,STRBUF    ;POINT TO A CONVERT BUFFER
  383.     CALL    BINASC        ;CONVERT TO DECIMAL ASCII
  384.     MVI    B,05H        ;BYTE COUNT PRINT STRING
  385.     LXI    H,STRBUF    ;POINT TO THE PRINT BUFFER
  386. DECPRT1:
  387.     MOV    A,M        ;GET PARAMETER CHARACTER
  388.     PUSH    H
  389.     CALL    CTYPE        ;PRINT AT CONSOLE
  390.     POP    H
  391.     INX    H        ;INCREMENT STRING POINTER
  392.     DCR    B        ;DEC BYTE COUNT
  393.     JNZ    DECPRT1        ;DONE WITH FIVE CHAR YET
  394.     RET
  395. ;
  396. ;
  397. ;DECIMAL PRINTING ROUTINE TEMPORARY BUFFER STRING SPACE
  398. ;
  399. STRBUF:
  400.     DS    14        ;RESERVE SOME BYTES FOR BUFFER
  401. ;
  402. ;
  403. ;CONSOLE SPACE PRINTING ROUTINE
  404. ;
  405. SP5:
  406.     MVI    A,' '        ;5 SPACES
  407.     CALL    CTYPE
  408. SP4:
  409.     MVI    A,' '        ;4 SPACES
  410.     CALL    CTYPE
  411. SP3:
  412.     MVI    A,' '        ;3 SPACES
  413.     CALL    CTYPE
  414. SP2:
  415.     MVI    A,' '        ;2 SPACES
  416.     CALL    CTYPE
  417. SP1:
  418.     MVI    A,' '        ;1 SPACE
  419.     CALL    CTYPE
  420.     RET
  421. ;
  422. ;
  423. ;
  424. ;
  425. * * * * * * * * * * * * * * * * * * * * *
  426. *                    *
  427. *    MTXWR: COPIES FILE TO MTX       *
  428. *                    *
  429. * * * * * * * * * * * * * * * * * * * * *
  430. ;
  431. ;THE CP/M FILE SPECIFIED IN THE COMMAND
  432. ;IS TRANSFERRED TO THE MTX DISK IN DRIVE B:
  433. ;
  434. MTXWR:
  435.     CALL    OPENFIL        ;OPEN THE FILE
  436.     LXI    H,0000H        ;SET INITIAL RECORD COUNT TO ZERO
  437.     SHLD    RECCNT
  438.     MVI    H,26        ;SET MAX UTILIZED SECTOR TO 26
  439.                 ;..MTX STARTS FILES AT LOGICAL SECTOR 26
  440.     SHLD    MAXSEC        ;STORE AWAY
  441.     MVI    A,00H
  442.     STA    MTXEOF        ;CLEAR MTX EOF FLAG
  443.     MVI    A,00H        ;SETUP FOR DIRECTORY SCAN
  444.     JMP    SCAN2        ;JUMP INTO LOOP
  445. SCAN1:
  446.     MVI    A,01H        ;SET SCAN CODE FOR NEXT ENTRY
  447. SCAN2:
  448.     CALL    MDIRSC        ;SCAN FOR NEXT DIRECTORY ENTRY
  449.     ORA    A        ;SET FLAGS FOR RETURN CODE
  450.     JNZ    MDIRFUL        ;EXIT FOR FULL DIRECTORY
  451. ;
  452.     MVI    B,06        ;SETUP FOR COMPARE OF FILE NAMES
  453.     LXI    D,FCB+1        ;..FOR 6 CHAR FROM CP/M FCB
  454.     LXI    H,MDENT        ;..TO MTX DIRECTORY ENTRY
  455.     CALL    COMPARE        ;GO DO THE COMPARE
  456.     ORA    A        ;CHECK    RETURN FLAG
  457.     JNZ    FEXEX        ;EXIT WITH FILE EXISTS MESSAGE
  458. ;
  459.     LDA    MDENT        ;FIRST BYTE OF NAME "FF" IF END
  460.     CPI    0FFH        ;ARE WE AT END OF LIST?
  461.     JZ    SCAN3        ;IF AT END THEN BALE OUT OF LOOP
  462. ;
  463.     LHLD    MAXSEC        ;SET TO UPDATE MAX USED SECTOR IF NEEDED
  464.     XCHG
  465.     LHLD    MDENT+14
  466.     MOV    A,L        ;COMPARE HIGH BYTE OF THIS ONE AND CURRENT MAX
  467.     CMP    E
  468.     JC    SCAN1        ;NO UPDATE NEEDED
  469.     JNZ    UDTMAX        ;IF HIGH BYTE GREATER THEN UPDATE MAX
  470.     MOV    A,H        ;COMPARE LOW BYTES OF THIS ONE AND CURRENT MAX
  471.     CMP    D
  472.     JC    SCAN1        ;NO UPDATE IF HIGHS EQUAL AND LOW NOT BIGGER
  473. UDTMAX:
  474.     SHLD    MAXSEC        ;STORE NEW BIG SEC NUM AT MAX SEC LOC
  475.     JMP    SCAN1        ;GO DO MORE DIRECTORY ENTRIES
  476. ;
  477. SCAN3:
  478.     MVI    B,06        ;MOVE FILE NAME INTO MTX DIRECTORY ENTRY
  479.     LXI    H,FCB+1
  480.     LXI    D,MDENT
  481. SCANAP:
  482.     MOV    A,M        ;GET CHAR FROM FCB AREA
  483.     ORI    080H        ;PUT ON TOP BIT FOR MTX COMPATIBILITY
  484.     STAX    D        ;PUT IN NEW DIRECTORY ENTRY
  485.     INX    H        ;BUMP POINTERS
  486.     INX    D
  487.     DCR    B        ;DEC NAME BYTE COUNT
  488.     JNZ    SCANAP
  489. ;
  490.     MVI    A,00        ;SET THE NEW FILE TYPE TO ZERO AS INDEXED FILE
  491.     STA    MDENT+6
  492.     STA    MDENT+7        ;SET KEYSIZE FIELD TO ZERO
  493.     STA    MDENT+10    ;SET HIGH BYTE OF RECORD SIZE TO ZERO
  494.     MVI    A,080H
  495.     STA    MDENT+11    ;SET RECORD SIZE TO 128 BYTES AS CP/M
  496.                 ;SECTOR SIZE
  497.     LHLD    MAXSEC        ;GET CURRENT MAX SECTOR AND PUT AS START
  498.     SHLD    MDENT+12
  499. ;
  500.     SHLD    MDENT+14    ;SET INITIAL END SECTOR
  501. MFILWLP:
  502.     CALL    RDSECT        ;READ A SECTOR FROM CP/M
  503.     JC    UPDATE        ;UPDATE MTX DIRECTORY IF DONE
  504.     LHLD    RECCNT        ;INC RECORD COUNT
  505.     CALL    MTXINC
  506.     SHLD    RECCNT
  507.     LXI    H,080H        ;MOVE SECTOR FROM CPM AREA
  508.     LXI    D,MTXBUF
  509.     CALL    MOVE128
  510.     CALL    RDSECT        ;READ ANOTHER SECTOR FROM CP/M
  511.     JC    UPDAFIL        ;UPDATE MTX DIRECTORY IF DONE
  512.     LHLD    RECCNT        ;INC RECORD COUNT
  513.     CALL    MTXINC
  514.     SHLD    RECCNT
  515.     LXI    H,080H        ;MOVE SECTOR FROM CP/M AREA
  516.     LXI    D,MTXBUF+128
  517.     CALL    MOVE128
  518. WRTENT:
  519.     LXI    H,MDENT+14    ;POINT TO SECTOR TO BE WRITTEN
  520.     MOV    D,M
  521.     INX    H
  522.     MOV    E,M
  523. ;
  524.     LXI    H,07B8H        ;CHECK IF DISK FULL
  525.     MOV    A,H
  526.     CMP    D
  527.     JNZ    NOTFUL
  528.     MOV    A,L
  529.     CMP    E
  530.     JZ    DSKFUL        ;EXIT WITH MESSAGE IF DISK IS FULL
  531. ;
  532. NOTFUL:
  533.     XCHG            ;HL=LOGICAL SECTOR TO WRITE
  534.     CALL    MWRSEC        ;GO WRITE CURRENT MTX SECTOR
  535.     LHLD    MDENT+14    ;INCREMENT END SECTOR
  536.     CALL    MTXINC
  537.     SHLD    MDENT+14
  538. ;
  539.     LDA    MTXEOF        ;SEE IF WE GOT TO END BEFORE
  540.     ORA    A
  541.     JNZ    UPDATE        ;GO TO UPDATE DIRECTORY IF END
  542. ;
  543.     JMP    MFILWLP        ;GO TO GET THE NEXT SECTOR FROM CP/M
  544. ;
  545. ;
  546. ;CP/M EOF ENCOUNTERED ON MIDDLE OF SECTOR NEEDS FILLING TO END
  547. ;    WE ARBITRARILY CHOOSE TO FILL WITH ZEROS.
  548. ;
  549. UPDAFIL:
  550.     LXI    H,MTXBUF+128    ;POINT TO SECOND HALF OF BUFFER
  551.     MVI    B,128        ;SET FILL COUNT
  552. SHFILL:
  553.     MVI    M,00H        ;PUT IN A ZERO
  554.     INX    H        ;BUMP POINTER
  555.     DCR    B        ;DEC BYTE COUNT
  556.     JNZ    SHFILL        ;MORE TO DO?
  557. ;
  558.     MVI    A,0FFH        ;SET END OF FILE FLAG
  559.     STA    MTXEOF
  560.     JMP    WRTENT        ;GO WRITE SECTOR
  561. ;
  562. ;FILE WRITTEN, NOW UPDATE THE DIRECTORY
  563. ;
  564. UPDATE:
  565.     XRA    A        ;INITIALIZE TWO SECTOR UPDATE FLAG
  566.     STA    U2SEC
  567. ;
  568.     LHLD    RECCNT        ;PUT RECORD COUNT INTO DIR ENTRY
  569.     MOV    A,H        ;CHECK IF THERE WAS NO CP/M FILE SIZE
  570.     ORA    L
  571.     JZ    NOSIZF        ;EXIT IF FILE FIZE IS ZERO
  572.     SHLD    MDENT+8
  573. ;
  574.     LXI    H,DIRBUF     ;MOVE DIRECTORY SECTOR TO OUTPUT BUFFER
  575.     LXI    D,MTXBUF
  576.     MVI    B,00H        ;SET THE COUNT FOR FULL 256 BYTE MOVE
  577.     CALL    MOVE
  578.     LDA    DIRSECI        ;GET DIRECTORY SECTOR INDEX    
  579.     LXI    H,MTXBUF-16
  580.     LXI    D,16        ;MAKE INSERT POINTER FOR NEW ENTRY
  581. UPDAT:
  582.     DAD    D
  583.     DCR    A
  584.     JNZ    UPDAT
  585. ;
  586.     XCHG            ;PUT INSERT POINTER IN DE
  587.     LXI    H,MDENT        ;POINT TO NEW DIRECTORY ENTRY
  588.     MVI    B,16        ;LENGTH OF DIRECTORY ENTRY
  589.     CALL    MOVE        ;MOVE INTO OUTPUT BUFFER
  590.     LDA    DIRSECI        ;SEE IF NEW ENTRY IS LAST IN SECTOR
  591.     CPI    016
  592.     JNZ    ONESEC        ;JUMP TO PUT END ENTRY IN THIS SECTOR
  593. ;
  594.     MVI    A,0FFH        ;SET U2SEC FLAG
  595.     STA    U2SEC
  596.     JMP    WDIRSEC        ;GO WRITE CURRENT SECTOR
  597. ;
  598. ONESEC:
  599.     MVI    A,0FFH         ;PUT "FF"ed OUT ENTRY INTO THIS SECTOR
  600.     MVI    B,16        ;ENTRY LENGTH-- DE OK FROM PREVIOUS MOVE
  601. ONESEC1:
  602.     STAX    D        ;PUT FF IN ENTRY
  603.     INX    D        ;INC FF'ING POINTER    
  604.     DCR    B        ;DEC BYTE COUNTER
  605.     JNZ    ONESEC1
  606. ;
  607. WDIRSEC:
  608.     LDA    MDIRSEC        ;GET THE DIRECTORY SECTOR NUMBER
  609.     MVI    H,0        ;MAKE TWO BYTE LOGICAL SECTOR NUMBER
  610.     MOV    L,A
  611.     CALL    MWRSEC        ;GO WRITE THE SECTOR OF DIRECTORY
  612.     LDA    U2SEC        ;CHECK IF WE SHOULD UPDATE TWO SECTORS
  613.     ORA    A
  614.     JNZ    GETSEC        ;IF SO GO PREPARE FOR IT
  615. ;
  616.     JMP    DONE        ;ALL DONE
  617. ;
  618. GETSEC:
  619.     XRA    A
  620.     STA    U2SEC        ;RESET UPDATE TWO SECTORS FLAG
  621.     LDA    MDIRSEC        ;GET CURRENT DIRECTORY SECTOR NUMBER
  622.     INR    A
  623.     STA    MDIRSEC        ;STORE THIS NEW ONE AWAY
  624.     CPI    01BH        ;SEE IF DIRECTORY FULL HERE
  625.     JZ    UDFULL        ;GO PRINT EXIT MESSAGE
  626. ;
  627.     MVI    H,0        ;MAKE TWO BYTE SECTOR NUMBER
  628.     MOV    L,A
  629.     CALL    MRDSEC        ;GO READ NEXT SECTOR
  630. ;
  631.     LXI    D,MTXBUF    ;POINT TO START OF DIRECTORY SECTOR
  632.     JMP    ONESEC        ;GO END THE PROCESS OF UPDATE ON SECOND SEC
  633. ;
  634. ;
  635. ;SUBROUTINE TO INCREMENT A REVERSE ORDER TWO BYTE PAIR
  636. ;
  637. MTXINC:
  638.     MOV    A,H        ;SET TO INCREMENT END SECTOR
  639.     MOV    H,L
  640.     MOV    L,A
  641.     INX    H        ;INC THE END SECTOR
  642.     MOV    A,H
  643.     MOV    H,L
  644.     MOV    L,A
  645.     RET
  646. ;
  647. ;
  648. ;EXIT POINT FROM WRITE IF MTX DIRECTORY IS FULL UPON UPDATE
  649. ;
  650. UDFULL:
  651.     CALL    ILPRT        ;PRINT DIRECTORY FULL MESSAGE
  652.     DB    CR,LF,'++MTX DIRECTORY FULL UPON UPDATE++'
  653.     DB    CR,LF,'++TRANSFERRED FILE EXISTS ON DISK++',CR,LF,0
  654.     JMP    EXIT
  655. ;
  656. ;
  657. ;EXIT POINT FROM WRITE IF MTX DIRECTORY IS FULL
  658. ;
  659. MDIRFUL:
  660.     CALL    ILPRT        ;PRINT DIRECTORY FULL MESSAGE
  661.     DB    CR,LF,'++MTX DIRECTORY MUST BE FULL++',CR,LF,0
  662.     JMP    EXIT
  663. ;
  664. ;
  665. ;EXIT POINT FROM WRITE IF NOTHING IN CP/M FILE
  666. ;
  667. NOSIZF:
  668.     CALL    ILPRT        ;PRINT NO SIZE TO CP/M FILE
  669.     DB    CR,LF,'++CP/M FILE EMPTY-NO MTX FILE CREATED++',CR,LF,0
  670.     JMP    EXIT
  671. ;
  672. ;
  673. ;EXIT POINT FROM WRITE IF MTX DISK GETS FULL
  674. ;
  675. DSKFUL:
  676.     CALL    ILPRT        ;PRINT DISK FULL MESSAGE
  677.     DB    CR,LF,'++FILE TOO BIG - MTX DISK FULL++'
  678.     DB    CR,LF,'++DIRECTORY NOT UPDATED WITH NEW FILE++',CR,LF,0
  679.     JMP    EXIT
  680. ;
  681. ;EXIT POINT FROM WRITE IF MTX FILE ALREADY EXISTS
  682. ;
  683. FEXEX:
  684.     CALL    ILPRT
  685.     DB    CR,LF,'++MTX FILE ALREADY EXISTS++'
  686.     DB    CR,LF,'++CHANGE NAME OF SOURCE FILE ON CP/M++',CR,LF,0
  687.     JMP    EXIT
  688. ;
  689. ;
  690. ;
  691. ;
  692. ;PARAMETER STORAGE AREA FOR MTX WRITE ROUTINE
  693. ;
  694. U2SEC    DB    00        ;USED TO SEE IF TWO SECTORS S/B SET IN DIR
  695. MAXSEC    DW    00        ;STORAGE FOR MAXIMUM USED LOGICAL SECTOR
  696. MTXEOF    DB    00        ;FLAG TO INDICATE IF END OF MTX FILE
  697. RECCNT    DW    00        ;CURRENT MTX FILE SIZE IN 128 BYTE RECORDS
  698. ;
  699. ;
  700. ;
  701. * * * * * * * * * * * * * * * * * * * * *
  702. *                    *
  703. *    MTXRD: COPY FILE FROM MTX       *
  704. *                    *
  705. * * * * * * * * * * * * * * * * * * * * *
  706. ;
  707. ;FETCHES AN MTX FILE AND THEN WRITES
  708. ;IT TO A CP/M FILE ON DRIVE A:
  709. ;
  710. MTXRD:
  711.     CALL    ERASFIL        ;ERASE THE CP/M FILE
  712.     CALL    MAKEFIL        ;..THEN MAKE NEW
  713.     MVI    A,00        ;SET SCAN FOR FIRST ENTRY
  714.     JMP    FIND2        ;JUMP INTO LOOP
  715. FIND1:
  716.     MVI    A,01        ;SET SCAN CODE FOR NEXT ENTRY
  717. FIND2:
  718.     CALL    MDIRSC        ;SCAN FOR NEXT DIRECTORY ENTRY
  719.     ORA    A        ;SET FLAGES FOR RETURN CODE
  720.     JNZ    MDNFEX        ;GO EXIT FOR NOT FOUND MTX FILE
  721.     LDA    MDENT        ;FIRST CHAR OF FILE NAME
  722.     CPI    0FFH        ;MUST BE AT END OF THE LIST IF "FF"
  723.     JZ    MDNFEX        ;GO EXIT FOR NOT FOUND MTX FILE
  724.     MVI    B,06H        ;SETUP FOR COMPARE FILE NAMES
  725.     LXI    D,FCB+1        ;..FOR 6 CHAR FROM FCB TO
  726.     LXI    H,MDENT        ;..MTX DIRECTORY ENTRY
  727.     CALL    COMPARE        ;GO COMPARE
  728.     ORA    A        ;CHECK THE RETURN FLAG
  729.     JZ    FIND1        ;NO NAME MATCH IF ZERO    
  730. ;
  731. ;FOUND FILE ON MTX DISK
  732. ;
  733. RMTXLP:
  734.     LDA    MDENT+6
  735.     CPI    000H        ;CKECK IF SOURCE FILE IS OF INDEXED TYPE
  736.     JNZ    NINDX        ;EXIT WITH ERROR IF NOT INDEXED FILE
  737. ;
  738.     LXI    H,MDENT+12    ;GET LOGICAL SECTOR NUMBER
  739.     MOV    D,M        ;..HIGH BYTE
  740.     INX    H
  741.     MOV    E,M        ;..LOW BYTE
  742.     INX    D        ;INCREMENT SECTOR FOR NEXT TIME
  743.     MOV    M,E        ;STORE BACK AWAY
  744.     DCX    H
  745.     MOV    M,D
  746.     DCX    D        ;GET BACK NUMBER OF ONE WE WANT
  747.     XCHG            ;LOGICAL SECTOR COUNT TO HL
  748.     CALL    MRDSEC        ;GO READ IT FROM MTX DISK
  749. ;
  750.     LXI    H,MTXBUF    ;MOVE 1ST HALF TO CP/M AREA
  751.     LXI    D,080H        ;..TO 128 BYTE PASS BUFFER FOR CP/M
  752.     CALL    MOVE128
  753.     CALL    WRSECT        ;MOVE DATA TO CP/M QUEUE
  754. ;
  755.     LXI    H,MTXBUF+128    ;MOVE 2ND HALF TO CP/M AREA
  756.     LXI    D,080H        ;..TO 128 BYTE PASS BUFFER FOR CP/M
  757.     CALL    MOVE128
  758.     CALL    WRSECT        ;MOVE 2ND HALF DATA TO CP/M QUEUE
  759. ;
  760.     LHLD    MDENT+12    ;GET CURRENT INCREMENTED LOGICAL SECTOR
  761.     XCHG            ;TO (DE). NOTE HI/LOW ORDER WRONG
  762.     LHLD    MDENT+14    ;GET DIRECTORY ENTRY 1+ ENDING SECTOR TO (HL)
  763.     MOV    A,H        ;COMPARE LOW BYTES OF SECTOR NUMBERS
  764.     CMP    D
  765.     JNZ    RMTXLP        ;BOTH MUST COMPARE FOR EQUALITY
  766.     MOV    A,L        ;NOW COMPARE HIGH BYTES OF SECTOR NUMBERS
  767.     CMP    E
  768.     JNZ    RMTXLP        ;AGAIN NO COMPARE SO MORE TO READ
  769. ;
  770. ;GOT EOF ON SECTOR - FLUSH BUFFERS, END
  771. ;
  772.     CALL    WRBLOCK        ;WRITE THE LAST BLOCK
  773.     CALL    CLOSFIL        ;CLOSE THE FILE
  774.     JMP    DONE        ;GO PRINT END OF TRANSFER MESSAGE
  775. ;
  776. ;
  777. ;
  778. MDNFEX:
  779.     CALL    ILPRT        ;PRINT MTX FILE NOT FOUND
  780.     DB    CR,LF,'++MTX FILE NOT FOUND++',CR,LF,0
  781.     JMP    EXIT
  782. ;
  783. ;
  784. ;
  785. NINDX:
  786.     CALL    ILPRT        ;PRINT MTX FILE TYPE NOT INDEXED TYPE
  787.     DB    CR,LF,'++MTX FILE NOT AN INDEXED FILE++',CR,LF,0
  788.     JMP    EXIT
  789. ;
  790. ;
  791. ;
  792. * * * * * * * * * * * * * * * * * * * * *
  793. *                    *
  794. *        SUBROUTINES        *
  795. *                    *
  796. * * * * * * * * * * * * * * * * * * * * *
  797. ;
  798. ;
  799. ;
  800. ;---->    ERASFIL: ERASE THE INCOMING FILE.
  801. ;
  802. ;IF IT EXISTS, ASK IF IT MAY BE ERASED.
  803. ;
  804. ERASFIL:
  805.     LXI    D,FCB        ;POINT TO CTL BLOCK
  806.     MVI    C,SRCHF     ;SEE IF IT..
  807.     CALL    BDOS        ;..EXISTS
  808.     INR    A        ;FOUND?
  809.     RZ            ;..NO, RETURN
  810.     CALL    ILPRT        ;PRINT:
  811.     DB    '++CP/M FILE EXISTS, TYPE Y TO ERASE: ',0
  812.     CALL    KEYIN        ;GET A CHARACTER FROM CONSOLE
  813.     ANI    5FH        ;MAKE UPPER CASE
  814.     CPI    'Y'        ;WANT ERASED?
  815.     JNZ    EXIT        ;QUIT IF NOT ERASE
  816.     CALL    CRLF        ;BACK TO START OF LINE
  817. ;
  818. ;ERASE OLD FILE
  819. ;
  820.     LXI    D,FCB        ;POINT TO FCB
  821.     MVI    C,ERASE        ;GET BDOS FNC
  822.     CALL    BDOS        ;DO THE ERASE
  823.     RET            ;FROM "ERASFIL"
  824. ;
  825. ;---->    MAKEFIL: MAKES THE FILE TO BE RECEIVED
  826. ;
  827. MAKEFIL:
  828.     LXI    D,FCB        ;POINT TO FCB
  829.     MVI    C,MAKE        ;GET BDOS FNC
  830.     CALL    BDOS        ;TO THE MAKE
  831.     INR    A        ;FF=BAD?
  832.     RNZ            ;OPEN OK
  833. ;
  834. ;DIRECTORY FULL - CAN'T MAKE FILE
  835. ;
  836.     CALL    ERXIT
  837.     DB    '++ERROR - CANNOT MAKE FILE++',CR,LF
  838.     DB    '++DIRECTORY MUST BE FULL++',CR,LF,'$'
  839. ;
  840. ;---->    OPENFIL: OPENS THE FILE TO BE SENT
  841. ;
  842. OPENFIL:
  843.     LXI    D,FCB        ;POINT TO FILE
  844.     MVI    C,OPEN        ;GET FUNCTION
  845.     CALL    BDOS        ;OPEN IT
  846.     INR    A        ;OPEN OK?
  847.     RNZ            ;FILE OPENED OK
  848.     CALL    ERXIT        ;..NO, ABORT
  849.     DB    '++CANNOT OPEN CP/M FILE++',CR,LF,'$'
  850. ;
  851. ;
  852. ;---->    CLOSFIL: CLOSES THE RECEIVED FILE
  853. ;
  854. CLOSFIL:
  855.     LXI    D,FCB        ;POINT TO FILE
  856.     MVI    C,CLOSE        ;GET FUNCTION
  857.     CALL    BDOS        ;CLOSE IT
  858.     INR    A        ;CLOSE OK?
  859.     RNZ            ;..YES, RETURN
  860.     CALL    ERXIT        ;..NO, ABORT
  861.     DB    '++CANNOT CLOSE CP/M FILE++',CR,LF,'$'
  862. ;
  863. ;---->    RDSECT: READS A SECTOR
  864. ;
  865. ;FOR SPEED, THIS ROUTINE BUFFERS UP 156
  866. ;SECTORS AT A TIME.
  867. ;
  868. RDSECT:
  869.     LDA    SECINBF        ;GET # SECT IN BUFF.
  870.     DCR    A        ;DECREMENT..
  871.     STA    SECINBF        ;..IT
  872.     CPI    0FFH        ;CHECK IF SECTOR COUNT UNDERFLOWS
  873.     JZ    RDBLOCK        ;EXHAUSTED?  NEED MORE.
  874.     LHLD    SECPTR        ;GET POINTER
  875.     LXI    D,80H        ;TO DATA 
  876.     CALL    MOVE128        ;MOVE TO BUFFER
  877.     SHLD    SECPTR        ;SAVE BUFFER POINTER
  878.     STC
  879.     CMC            ;CLEAR CARRY SO EOF NOT INDICATED
  880.                 ;ON NORMAL RETURN
  881.     RET            ;FROM "READSEC"
  882. ;
  883. ;BUFFER IS EMPTY - READ IN ANOTHER BLOCK OF 156
  884. ;
  885. RDBLOCK:
  886.     LDA    EOFLG        ;GET EOF FLAG
  887.     CPI    1        ;IS IT SET?
  888.     STC            ;TO SHOW EOF
  889.     RZ            ;GOT EOF
  890.     MVI    C,00H        ;SELECT DRIVE A:
  891.     CALL    SELDSK
  892.     MVI    C,0        ;SECTORS IN BLOCK
  893.     LXI    D,DBUF        ;TO DISK BUFFER
  894. RDSECLP:
  895.     PUSH    B
  896.     PUSH    D
  897.     MVI    C,STDMA        ;SET DMA..
  898.     CALL    BDOS        ;..ADDR
  899.     LXI    D,FCB
  900.     MVI    C,READ
  901.     CALL    BDOS
  902.     POP    D
  903.     POP    B
  904.     ORA    A        ;READ OK?
  905.     JZ    RDSECOK        ;YES
  906.     DCR    A        ;EOF?
  907.     JZ    REOF        ;GOT EOF
  908. ;
  909. ;READ ERROR
  910. ;
  911.     CALL    ERXIT
  912.     DB    '++CP/M FILE READ ERROR++',CR,LF,'$'
  913. ;
  914. RDSECOK:
  915.     LXI    H,80H
  916.     DAD    D        ;TO NEXT BUFF
  917.     XCHG            ;BUFF TO DE
  918.     INR    C        ;MORE SECTORS?
  919.     MOV    A,C        ;GET COUNT
  920.     CPI    156        ;DONE?
  921.     JZ    RDBFULL        ;..YES, BUF IS FULL
  922.     JMP    RDSECLP        ;READ MORE
  923. ;
  924. REOF:
  925.     MVI    A,1
  926.     STA    EOFLG        ;SET EOF FLAG
  927.     MOV    A,C
  928. ;
  929. ;BUFFER IS FULL, OR GOT EOF
  930. ;
  931. RDBFULL:
  932.     STA    SECINBF        ;STORE SECTOR COUNT
  933.     LXI    H,DBUF        ;INIT BUFFER..
  934.     SHLD    SECPTR        ;..POINTER
  935.     LXI    D,80H        ;RESET..
  936.     MVI    C,STDMA        ;..DMA..
  937.     CALL    BDOS        ;..ADDR
  938.     JMP    RDSECT        ;PASS SECT TO CALLER
  939. ;
  940. ;---->    WRSECT: WRITE A SECTOR
  941. ;
  942. ;WRITES THE SECTOR INTO A BUFFER. WHEN 156
  943. ;HAVE BEEN WRITTEN, WRITES THE BLOCK TO DISK.
  944. ;
  945. ;ENTRY POINT "WRBLOCK" FLUSHES THE BUFFER AT EOF.
  946. ;
  947. WRSECT:
  948.     LHLD    SECPTR        ;GET BUFF ADDR
  949.     XCHG            ;TO DE FOR MOVE
  950.     LXI    H,80H        ;FROM HERE
  951.     CALL    MOVE128        ;MOVE TO BUFFER
  952.     XCHG            ;SAVE NEXT..
  953.     SHLD    SECPTR        ;..BLOCK POINTER
  954.     LDA    SECINBF        ;BUMP THE..
  955.     INR    A        ;..SECTOR #..
  956.     STA    SECINBF        ;..IN THE BUFF
  957.     CPI    156        ;HAVE WE 156?
  958.     RNZ            ;NO, RETURN
  959. ;
  960. ;---->    WRBLOCK: WRITES A BLOCK TO DISK
  961. ;
  962. WRBLOCK:
  963.     LDA    SECINBF        ;# SECT IN BUFFER
  964.     ORA    A        ;0 MEANS END OF FILE
  965.     RZ            ;NONE TO WRITE
  966.     PUSH    PSW        ;SAVE SECINBUF
  967.     MVI    C,00H        ;SELECT DISK DRIVE A:
  968.     CALL    SELDSK
  969.     POP    PSW        ;GET SECINBUF BACK
  970.     MOV    C,A        ;SAVE COUNT
  971.     LXI    D,DBUF        ;POINT TO DISK BUFF
  972. DKWRLP:
  973.     PUSH    H
  974.     PUSH    D
  975.     PUSH    B
  976.     MVI    C,STDMA        ;SET DMA
  977.     CALL    BDOS        ;TO BUFFER
  978.     LXI    D,FCB        ;THEN WRITE
  979.     MVI    C,WRITE        ;..THE..
  980.     CALL    BDOS        ;..BLOCK
  981.     POP    B
  982.     POP    D
  983.     POP    H
  984.     ORA    A
  985.     JNZ    WRERR        ;OOPS, ERROR
  986.     LXI    H,80H        ;LENGTH OF 1 SECT
  987.     DAD    D        ;HL= NEXT BUFF
  988.     XCHG            ;TO DE FOR SETDMA
  989.     DCR    C        ;MORE SECTORS?
  990.     JNZ    DKWRLP        ;..YES, LOOP
  991.     XRA    A        ;GET A ZERO
  992.     STA    SECINBF        ;RESET # OF SECTORS
  993.     LXI    H,DBUF        ;RESET BUFFER..
  994.     SHLD    SECPTR        ;..POINTER
  995.     RET
  996. ;
  997. WRERR:
  998.     CALL    ERXIT        ;EXIT W/MSG:
  999.  
  1000.     DB    '++ERROR WRITING CP/M FILE++',CR,LF,'$'
  1001. ;
  1002. ;
  1003. ;
  1004. ;---->    PROCOPT: PROCESS COMMAND OPTIONS
  1005. ;SAVES THE PROGRAM OPTION IN 'OPTION';
  1006. ;
  1007. PROCOPT:
  1008.     LXI    D,FCB+1        ;TO PROGRAM OPT.
  1009.     LDAX    D        ;GET OPTION
  1010.     STA    OPTION        ;SAVE IT
  1011.     RET            ;FROM 'PROCOPT'
  1012. ;
  1013. ;DONE - CLOSE UP SHOP
  1014. ;
  1015. DONE:
  1016.     CALL    ILPRT
  1017.     DB    CR,LF,'TRANSFER COMPLETE'
  1018.     DB    CR,LF,0
  1019. ;
  1020.     JMP    EXIT        ;DONE, GO BACK
  1021. ;
  1022. ;
  1023. ;ROUTINE MOVES THE FILENAME FROM THE SECOND FCB
  1024. ;TO THE FIRST
  1025. ;
  1026. MOVEFCB:
  1027.     LXI    H,FCB+16     ;FROM
  1028.     LXI    D,FCB        ;TO
  1029.     MVI    B,16        ;LEN
  1030.     CALL    MOVE        ;DO THE MOVE
  1031.     XRA    A        ;GET 0
  1032.     STA    FCBSNO        ;ZERO SECTOR #
  1033.     STA    FCB        ;..AND DRIVE DESIGNATOR
  1034.     STA    FCBEXT        ;..AND EXTENT
  1035.     RET
  1036. ;
  1037. ;
  1038. ; MTX DOUBLE DENSITY FLOPPY DISK ACCESS ROUTINE FOR DRIVE B:
  1039. ; ON AN ICOM 3812 RUNNING LIFEBOAT CP/M VER 1.4
  1040. ;
  1041. ;
  1042. ;
  1043. ;---->  MRDSEC: READS A GIVEN SECTOR ACCORDING
  1044. ;        TO MTX CONVENTION. REGISTER PAIR (HL)
  1045. ;        CONTAINS THE LOGICAL SECTOR NUMBER.
  1046. ;
  1047. MRDSEC:
  1048.     CALL    MTXSCAL        ;GET OURSELVES A TRACK AND SECTOR
  1049.     PUSH    H        ;SAVE SECTOR NUMBER
  1050.     PUSH    B        ;SAVE TRACK NUMBER
  1051.     MVI    C,01H        ;LETS SELECT B: FOR MTX ACCESS
  1052.     CALL    SELDSK        ;LET BIOS SELECT DISK
  1053.     POP    B        ;GET TRACK NUMBER FOR NEXT CALL
  1054.     MOV    C,B
  1055.     CALL    SETTRK        ;HAVE BIOS HANDLE TRACK SEEK
  1056.     LXI    B,MTXBUF    ;SET DMA ADDRESS FOR BUFFER
  1057.     CALL    SETDMA
  1058.     POP    H        ;GET SECTOR NUMBER
  1059.     MOV    C,L        ;PUT FOR BIOS
  1060.     PUSH    B        ;SAVE FOR 2ND 128 BYTES
  1061.     CALL    SETSEC        ;BIOS POINT TO FIRST HALF
  1062.     CALL    RDSEC        ;READ THE SECTOR INTO BUFFER
  1063.     ORA    A        ;LOOK TO SEE IF READ ERROR
  1064.     JNZ    MRDER        ;TELL OF MTX READ ERROR
  1065.     LXI    B,MTXBUF+128
  1066.     CALL    SETDMA        ;FIX DMA ADDR FOR 2ND HALF
  1067.     POP    B        ;FIX FOR SEC +1 TO GET 2ND HALF
  1068.     INR    C
  1069.     CALL    SETSEC
  1070.     CALL    RDSEC        ;READ 2ND HALF
  1071.     ORA    A        ;LOOK AGAIN TO SEE IF READ ERROR
  1072.     JNZ    MRDER
  1073.     RET            ;GO BACK IF NO ERRORS DETECTED
  1074. ;
  1075. ;MTX DISK READ ERROR
  1076. ;
  1077. MRDER:
  1078.     CALL    ERXIT
  1079.     DB    '++MTX DISK READ ERROR++$'
  1080. ;
  1081. ;
  1082. ;---->  MWRSEC:    WRITES A GIVEN SECTOR ACCORDING 
  1083. ;        TO MTX CONVENTION. REGISTER PAIR (HL)
  1084. ;        CONTAINS THE LOGICAL SECTOR NUMBER.
  1085. ;
  1086. ;
  1087. MWRSEC:
  1088.     CALL    MTXSCAL        ;GET OURSELVES A TRACK AND SECTOR
  1089.     PUSH    H        ;SAVE SECTOR NUMBER
  1090.     PUSH    B        ;SAVE TRACK NUMBER
  1091.     MVI    C,01H        ;LETS SELECT B: FOR MTX ACCESS
  1092.     CALL    SELDSK        ;LET BIOS SELECT DISK
  1093.     POP    B        ;GET TRACK NUMBER FOR NEXT CALL
  1094.     MOV    C,B
  1095.     CALL    SETTRK        ;HAVE BIOS HANDLE TRACK SEEK
  1096.     LXI    B,MTXBUF    ;SET DMA ADDRESS FOR BUFFER
  1097.     CALL    SETDMA
  1098.     POP    H        ;GET SECTOR NUMBER
  1099.     MOV    C,L        ;PUT FOR BIOS
  1100.     PUSH    B        ;SAVE FOR 2ND 128 BYTES
  1101.     CALL    SETSEC        ;BIOS POINT TO FIRST HALF
  1102.     CALL    WRTSEC        ;WRITE THE SECTOR FROM BUFFER
  1103.     ORA    A        ;LOOK TO SEE IF WRITE ERROR
  1104.     JNZ    MWRER        ;TELL OF MTX WRITE ERROR
  1105.     LXI    B,MTXBUF+128
  1106.     CALL    SETDMA        ;FIX DMA ADDR FOR 2ND HALF
  1107.     POP    B        ;FIX FOR SEC +1 TO GET 2ND HALF
  1108.     INR    C
  1109.     CALL    SETSEC
  1110.     CALL    WRTSEC        ;WRITE 2ND HALF
  1111.     ORA    A        ;LOOK AGAIN TO SEE IF WRITE ERROR
  1112.     JNZ    MWRER
  1113.     RET            ;GO BACK IF NO ERRORS DETECTED
  1114. ;
  1115. ;MTX DISK WRITE ERROR
  1116. ;
  1117. MWRER:
  1118.     CALL    ERXIT
  1119.     DB    '++MTX DISK WRITE ERROR++$'
  1120. ;
  1121. ;
  1122. ;---->  MTXSCAL: TRANSLATES MTX LOGICAL SECTOR TO
  1123. ;         TRACK AND PHYSICAL SECTOR NUMBERS
  1124. ;
  1125. ;         ENTRY WITH DOUBLE BYTE LOGICAL SECTOR
  1126. ;             NUMBER IN (HL).
  1127. ;         EXIT WITH TRACK IN (B) AND PHYSICAL SECTOR
  1128. ;            IN (L)
  1129. ;
  1130. ;         NOTE THAT THE SUBSEQUENT ROUTINE WILL HAVE
  1131. ;         READ SECTORS (L) AND (L+1) TO OBTAIN ALL OF
  1132. ;         THE MTX SECTORS DATA.
  1133. ;
  1134. MTXSCAL:
  1135.     LXI    D,-26        ;SET TO CALCULATE TRACK NUMBER
  1136.     MVI    B,00H        ;INITIAL TRACK COUNTER
  1137. TRCLP1:
  1138.     INR    B        ;TRACK LOOP COUNTER INCREMENT
  1139.     DAD    D        ;SUBTRACT SECTOR NUMBERS MOD 26        
  1140.     JC    TRCLP1        ;LOOP IN SUBTRACT TILL WE UNDERFLOW
  1141. ;
  1142.     LXI    D,26        ;SET THE HL PAIR TO REAL LOGICAL SECTOR
  1143.                 ; ON THIS TRACK
  1144.     DAD    D
  1145. ;
  1146.     XCHG            ;PUT LOGICAL SECTOR IN DE FOR NOW
  1147.     LXI    H,TRANTBL    ;GET BASE OF TRANSLATION TABLE
  1148.     DAD    D        ;INDEX INTO TABLE
  1149.     MOV    L,M        ;GET PHYSICAL NUMBER
  1150.     RET
  1151. ;
  1152. ;
  1153. ;MTX LOGICAL TO PHYSICAL SECTOR TRANSLATION TABLE
  1154. ;    TABLE ENTRIES ARE IN LOGICAL ORDER
  1155. ;    TRACK LOGICAL SECTOR ZERO MAPS TO PHYSICAL #1
  1156. ;    ALSO NOTE THAT THIS TABLE ASSUMES THAT DISK
  1157. ;    SOFTWARE THINKS TRACK HAS 52 128 BYTE SECTORS
  1158. ;
  1159. TRANTBL:
  1160.     DB    1
  1161.     DB    5
  1162.     DB    9
  1163.     DB    13
  1164.     DB    17
  1165.     DB    21
  1166.     DB    25
  1167.     DB    29
  1168.     DB    33
  1169.     DB    37
  1170.     DB    41
  1171.     DB    45
  1172.     DB    49
  1173.     DB    3
  1174.     DB    7
  1175.     DB    11
  1176.     DB    15
  1177.     DB    19
  1178.     DB    23
  1179.     DB    27
  1180.     DB    31
  1181.     DB    35
  1182.     DB    39
  1183.     DB    43
  1184.     DB    47
  1185.     DB    51
  1186. ;
  1187. ;
  1188. ;---->    INITADR: INIT'S CP/M BDOS ADDRESSES
  1189. ;
  1190. ;THIS ROUTINE FILLS IN THE ADDRESSES OF VARIOUS
  1191. ;JUMP VECTOR ENTRY POINTS SO THAT CP/M BDOS
  1192. ;IS BYPASSED WHILE ACCESSING THE MTX DISK
  1193. ;IN DRIVE B: SO THAT THE MODIFIED LOGICAL
  1194. ;SECTORING MAY BE USED.
  1195. ;
  1196. INITADR:
  1197.     LHLD    1        ;GET WARM BOOT ADDR
  1198.     LXI    D,015H        ;OFFSET TO HOME VECTOR
  1199.     DAD    D        ;TO HOME DISK ROUTINE
  1200.     SHLD    HOME+1      ;SET INTERNAL HOME VECTOR
  1201.     LXI    D,003H        ;OFFSET TO NEXT VECTOR
  1202.     DAD    D        ;TO SELECT DISK ROUTINE
  1203.     SHLD     SELDSK+1    ;SET INTERNAL SELDSK VECTOR
  1204.     DAD    D        ;TO SET TRACK ROUTINE
  1205.     SHLD    SETTRK+1    ;SET INTERNAL SETTRK VECTOR
  1206.     DAD    D        ;TO SET SECTOR ROUTINE
  1207.     SHLD    SETSEC+1    ;SET INTERNAL SETSEC VECTOR
  1208.     DAD    D        ;TO SET DMA ADDRESS ROUTINE
  1209.     SHLD    SETDMA+1    ;SET INTERNAL SETDMA VECTOR
  1210.     DAD    D        ;TO READ SECTOR ROUTINE
  1211.     SHLD    RDSEC+1        ;SET INTERNAL READ VECTOR
  1212.     DAD    D        ;TO WRITE SECTOR ROUTINE
  1213.     SHLD    WRTSEC+1    ;SET INTERNAL WRITE VECTOR
  1214. ;
  1215.     RET
  1216. ;
  1217. ;
  1218. ;----> ENTRY POINTS FOR BIOS DISK ACCESS PRIMATIVES-ADDRESSES SETUP AT INIT
  1219. ;
  1220. HOME:
  1221.     JMP    $-$        ;HOME DISK INTERNAL VECTOR
  1222. SELDSK:
  1223.     JMP    $-$        ;SELECT DISK INTERNAL VECTOR
  1224. SETTRK:
  1225.     JMP    $-$        ;SET TRACK INTERNAL VECTOR
  1226. SETSEC:
  1227.     JMP    $-$        ;SET SECTOR INTERNAL VECTOR
  1228. SETDMA:
  1229.     JMP    $-$        ;SET DMA ADDRESS INTERNAL VECTOR
  1230. RDSEC:
  1231.     JMP    $-$        ;READ SECTOR INTERNAL VECTOR
  1232. WRTSEC:
  1233.     JMP    $-$        ;WRITE SECTOR INTERNAL VECTOR
  1234. ;
  1235. ;
  1236. ;
  1237. ;SETUP A DATA BUFFER FOR MTX SECTOR WHICH IS 256 BYTES LONG
  1238. ;IT TAKES TWO CP/M 1.4 128 BYTE SECTOR READS TO FILL THE
  1239. ;MTX LOGICAL SECTOR BUFFER.
  1240. ;
  1241.     DS    20        ;DUMMY BUFFER PAD
  1242. MTXBUF:
  1243.     DS    256        ;MTX READ DATA BUFFER
  1244.     DS    20        ;BUFFER PAD
  1245. ;
  1246. ;
  1247. ;
  1248. ;
  1249. ;---->  KEYIN: GETS A KEY CODE IN FROM CONSOLE
  1250. ;
  1251. KEYIN:
  1252.     PUSH    B        ;SAVE..
  1253.     PUSH    D        ;..ALL..
  1254.     PUSH    H        ;..REGS
  1255.     MVI    C,RDCON        ;GET CONSOLE CHARACTER FUNCTION CODE
  1256.     CALL    BDOS        ;GET CHARACTER
  1257.     MOV    A,E
  1258.     POP    H        ;RESTORE..
  1259.     POP    D        ;..ALL..
  1260.     POP    B        ;..REGS
  1261.     RET
  1262. ;
  1263. ;
  1264. ;---->    CTYPE: TYPES VIA CP/M SO TABS ARE EXPANDED
  1265. ;
  1266. CTYPE:
  1267.     PUSH    B        ;SAVE..
  1268.     PUSH    D        ;..ALL..
  1269.     PUSH    H        ;..REGS
  1270.     MOV    E,A        ;CHAR TO E
  1271.     MVI    C,WRCON        ;GET BDOS FNC
  1272.     CALL    BDOS        ;PRIN THE CHR
  1273.     POP    H        ;RESTORE..
  1274.     POP    D        ;..ALL..
  1275.     POP    B        ;..REGS
  1276.     RET            ;FROM "CTYPE"
  1277. ;
  1278. CRLF:
  1279.     MVI    A,CR
  1280.     CALL    CTYPE
  1281.     MVI    A,LF
  1282.     CALL    CTYPE
  1283.     RET
  1284. ;
  1285. ;
  1286. ;HEX OUTPUT
  1287. ;
  1288. HEXO:
  1289.     PUSH    PSW        ;SAVE FOR RIGHT DIGIT
  1290.     RAR            ;RIGHT..
  1291.     RAR            ;..JUSTIFY..
  1292.     RAR            ;..LEFT..
  1293.     RAR            ;..DIGIT..
  1294.     CALL    NIBBL        ;PRINT LEFT DIGIT
  1295.     POP    PSW        ;RESTORE RIGHT
  1296.     CALL    NIBBL        ;PRINT RIGHT DIGIT
  1297.     RET
  1298. ;
  1299. ;
  1300. NIBBL:
  1301.     ANI    0FH        ;ISOLATE DIGIT
  1302.     CPI    10        ;IS IS <10?
  1303.     JC    ISNUM        ;YES, NOT ALPHA
  1304.     ADI    7        ;ADD ALPHA BIAS
  1305. ISNUM:
  1306.     ADI    '0'        ;MAKE PRINTABLE
  1307.     CALL    CTYPE        ;..THEN TYPE IT
  1308.     RET
  1309. ;
  1310. ;
  1311. ;---->    ILPRT: INLINE PRINT OF MSG
  1312. ;
  1313. ;THE CALL TO ILPRT IS FOLLOWED BY A MESSAGE,
  1314. ;BINARY 0 AS THE END.  BINARY 1 MAY BE USED TO
  1315. ;PAUSE (MESSAGE 'PRESS RETURN TO CONTINUE')
  1316. ;
  1317. ILPRT:
  1318.     XTHL            ;SAVE HL, GET HL=MSG
  1319. ILPLP:
  1320.     MOV    A,M        ;GET CHAR
  1321.     ORA    A        ;END OF MSG?
  1322.     JZ    ILPRET        ;..YES, RETURN
  1323.     CPI    1        ;PAUSE?
  1324.     JZ    ILPAUSE        ;..YES
  1325.     CALL    CTYPE        ;TYPE THE CHARACTER OF MESSAGE
  1326. ILPNEXT:
  1327.     INX    H        ;TO NEXT CHAR
  1328.     JMP    ILPLP        ;LOOP
  1329. ;
  1330. ;PAUSE WHILE TYPING HELP SO INFO DOESN'T
  1331. ;    SCROLL OFF OF VIDEO SCREENS
  1332. ;
  1333. ILPAUSE:
  1334.     CALL    ILPRT        ;PRINT:
  1335.  
  1336.     DB    CR,LF,'PRESS RETURN TO CONTINUE OR ^C TO EXIT'
  1337.     DB    CR,LF,0
  1338.     CALL    KEYIN        ;GET ANY CHAR
  1339.     CPI    'C'-40H        ;REBOOT?
  1340.     JZ    EXIT        ;YES.
  1341.     JMP    ILPNEXT        ;LOOP
  1342. ;
  1343. ILPRET:
  1344.     XTHL            ;RESTORE HL
  1345.     RET            ; & RETURN ADDR PAST MESSAGE
  1346. ;
  1347. ;---->    PRTMSG: PRINTS MSG POINTED TO BY (DE)
  1348. ;
  1349. ;A '$' IS THE ENDING DELIMITER FOR THE PRINT.
  1350. ;NO REGISTERS SAVED.
  1351. ;
  1352. PRTMSG:
  1353.     MVI    C,PRINT        ;GET BDOS FNC
  1354.     JMP    BDOS        ;PRINT MESSAGE, RETURN
  1355. ;
  1356. ;---->    ERXIT: EXIT PRINTING MSG FOLLOWING CALL
  1357. ;
  1358. ERXIT:
  1359.     POP    D        ;GET MESSAGE
  1360.     CALL    PRTMSG        ;PRINT IT
  1361. ;
  1362. EXIT:
  1363.     MVI    C,00H        ;SET SELECTED UNIT BACK TO A:
  1364.     CALL    SELDSK
  1365.     LXI    D,080H        ;RESET DEFAULT DMA ADDRESS FOR EXIT
  1366.     MVI    C,STDMA
  1367.     CALL    BDOS
  1368.     LHLD    STACK        ;GET ORIGINAL STACK
  1369.     SPHL            ;RESTORE IT
  1370.     JMP    WBOOT        ;GO DO A WARM BOOT OF CP/M SO THIS 
  1371.                 ;THING WILL WORK IN A SUBMIT FILE
  1372. ;
  1373. ;MOVE 128 CHARACTERS
  1374. ;
  1375. MOVE128:
  1376.     MVI    B,128        ;SET MOVE COUNT
  1377. ;
  1378. ;MOVE FROM (HL) TO (DE) LENGTH IN (B)
  1379. ;
  1380. MOVE:
  1381.     MOV    A,M        ;GET A CHAR
  1382.     STAX    D        ;STORE IT
  1383.     INX    H        ;TO NEXT "FROM"
  1384.     INX    D        ;TO NEXT "TO"
  1385.     DCR    B        ;MORE?
  1386.     JNZ    MOVE        ;..YES, LOOP
  1387.     RET            ;..NO, RETURN
  1388. ;
  1389. ;
  1390. ;COMPARE FROM (HL) TO (DE) FOR (B) BYTES
  1391. ;RETURN WITH A REGISTER:
  1392. ;    =00 IF NO COMPARE
  1393. ;    =FF IF VALID COMPARE
  1394. ;
  1395. COMPARE:
  1396.     LDAX    D        ;GET A CHAR
  1397.     CMP    M        ;CHECK AGAINST OTHER
  1398.     JNZ    COMFAL        ;GO EXIT FOR FAIL
  1399.     INX    H        ;INCREMENT COMPARE POINTERS
  1400.     INX    D
  1401.     DCR    B        ;DECREMENT CHAR COUNT
  1402.     JNZ    COMPARE        ;MORE?
  1403.     MVI    A,0FFH        ;EXIT FOR GOOD COMPARE
  1404.     RET
  1405. COMFAL:
  1406.     XRA    A        ;EXIT FOR NON COMPARE
  1407.     RET
  1408. ;
  1409. ;
  1410. ;----> BINASC: CONVERTS A 16 BIT BINARY NUMBER TO ASCII
  1411. ;        INPUT NUMBER ASSUMED TO BE IN HL AND
  1412. ;        OUTPUT ASCII 5 CHARACTER BUFFER IS POINTED
  1413. ;        TO BY DE. MAXIMUM NUMBER FOR CONVERSION IS
  1414. ;        THE EQUIVALENT OF 16 BITS BINARY.
  1415. ;
  1416. BINASC:
  1417.     PUSH    PSW        ;SAVE REGISTERS
  1418.     PUSH    B
  1419.     PUSH    D
  1420.     LXI    B,004H        ;FIX DE TO POINT TO END OF BUFFER
  1421.     XCHG
  1422.     DAD    B
  1423.     XCHG
  1424.     PUSH    D        ;SAVE ASCII POINTER
  1425.     MVI    A,05H        ;GET A DIGIT COUNT
  1426.     STA    DIGCNT
  1427. NDIG:
  1428.     LXI    B,-10        ;RADIX FOR CONVERSION
  1429.     LXI    D,-1        ;THIS BECOMES NO DIVIDED BY RADIX
  1430. DX:
  1431.     DAD    B        ;SUBTRACT 10
  1432.     INX    D
  1433.     JC    DX
  1434.     LXI    B,10
  1435.     DAD    B        ;ADD RADIX BACK IN ONCE
  1436.     XCHG
  1437.     MOV    A,E
  1438.     ADI    '0'        ;CONVERT FROM BCD TO ASCII
  1439.     POP    D        ;GET ASCII BUFFER POINTER
  1440.     STAX    D        ;STORE ASCII CHARACTER
  1441.     DCX    D        ;ADJUST ASCII POINTER
  1442.     LDA    DIGCNT        ;CHECK IF CONVERSION DONE
  1443.     DCR    A
  1444.     JZ    DDIG        ;EXIT IF DONE
  1445.     STA    DIGCNT
  1446.     PUSH    D        ;SAVE ASCII POINTER
  1447.     JMP    NDIG        ;GO DO NEXT DIGIT
  1448. DDIG:
  1449.     POP    D        ;RESTORE REGISTERS
  1450.     POP    B
  1451.     POP    PSW
  1452.     RET
  1453. ;
  1454. ;
  1455. ;BINASC ROUTINE STORAGE ALLOCATIONS
  1456. ;
  1457. DIGCNT    DB    00        ;PLACE TO STORE ASCII DIGIT COUNT
  1458. ;
  1459. ;
  1460. ;
  1461. ;
  1462. ;    ----------------
  1463. ;
  1464. ;PROGRAM DATA AREA SPACE ALLOCATIONS
  1465. ;
  1466. OPTION    DB    0        ;PROGRAM OPTION
  1467. ;
  1468. ;
  1469. ;FOLLOWING 3 USED BY THE CP/M DISK BUFFERING ROUTINES
  1470. ;
  1471. EOFLG    DB    0        ;EOF FLAG (1=TRUE)
  1472. SECPTR    DW    DBUF
  1473. SECINBF    DB    0        ;# OF SECTORS IN BUFFER
  1474. ;
  1475. ;
  1476. ;MTX FILE HANDLER PARAMETER STORAGE LOCATIONS
  1477. ;
  1478.     DS    20
  1479. MDENT    DS    16        ;TEMPORARY STORAGE FOR A DIRECTORY ENTRY
  1480.     DS    20
  1481. ;
  1482. ;
  1483. ;SETUP A STACK AREA
  1484. ;
  1485.     DS    400        ;STACK AREA
  1486. STACK    DS    2        ;STACK POINTER
  1487. ;
  1488. ;+++++++++
  1489. ;+++++++++
  1490. ;++
  1491. ;++ NOTE: THE FOLLOWING DISK DATA BUFFERS ARE ALLOCATED
  1492. ;++       OVER THE HELP FILE AND NON DISK I/O SOFTWARE
  1493. ;++
  1494. ;+++++++++
  1495. ;+++++++++
  1496. ;
  1497. ;
  1498. ;16 SECTOR CP/M DISK BUFFER 
  1499. ;
  1500.     DS    20
  1501. DBUF    EQU    $+1        ;16 SECTOR CP/M DISK BUFFER
  1502. ;
  1503. ;INVALID COMMAND
  1504. ;
  1505. BADOPT:
  1506.     PUSH    PSW        ;SAVE BAD OPTION
  1507.     MVI    A,'['
  1508.     CALL    CTYPE
  1509.     POP    PSW
  1510.     CALL    CTYPE
  1511.     CALL    ILPRT        ;EXIT W/ERROR
  1512.     DB    '] INVALID OPTION FOR PROGRAM SELECTION '
  1513.     DB    'COMMAND - ',CR,LF
  1514.     DB    'PRESS CTL-C TO ABORT',1,0
  1515. ;
  1516. HELP:
  1517.     CALL    ILPRT
  1518.     DB    CR,LF,CR,LF,'FORMAT FOR COMMAND IS:',CR,LF,CR,LF
  1519.     DB    'MTX # FILENAME',CR,LF,CR,LF
  1520.     DB    'WHERE # IS A 1 CHARACTER PROGRAM OPTION,',CR,LF
  1521.     DB    'PROGRAM OPTIONS:',CR,LF
  1522.     DB    '    R TO READ AN MTX FILE FROM B:',CR,LF
  1523.     DB    '    W TO WRITE AN MTX FILE TO B:',CR,LF
  1524.     DB    '    D TO VIEW THE MTX DIRECTORY ON B:',CR,LF
  1525.     DB    '    H TO PRINT THIS HELP FILE',CR,LF,CR,LF,0
  1526.     JMP    EXIT
  1527. ;
  1528. ;
  1529. ; BDOS EQUATES (VERSION 2)
  1530. ;
  1531. RDCON    EQU    1
  1532. WRCON    EQU    2
  1533. PRINT    EQU    9
  1534. CONST    EQU    11        ;CONSOLE STAT
  1535. OPEN    EQU    15        ;0FFH=NOT FOUND
  1536. CLOSE    EQU    16        ;    "    "
  1537. SRCHF    EQU    17        ;    "    "
  1538. SRCHN    EQU    18        ;    "    "
  1539. ERASE    EQU    19        ;NO RET CODE
  1540. READ    EQU    20        ;0=OK, 1=EOF
  1541. WRITE    EQU    21        ;0=OK, 1ERR, 2=?, 0FFH=NO DIR SPC
  1542. MAKE    EQU    22        ;0FFH=BAD
  1543. REN    EQU    23        ;0FFH=BAD
  1544. STDMA    EQU    26        ;SET DMA
  1545. BDOS    EQU    5
  1546. REIPL    EQU    0
  1547. FCB    EQU    5CH        ;SYSTEM FCB
  1548. FCBEXT    EQU    FCB+12        ;FILE EXTENT
  1549. FCBSNO    EQU    FCB+32        ;SECTOR #
  1550. FCB2    EQU    6CH        ;SECOND FCB
  1551.     END
  1552.