home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / lambda / soundpot / f / mload14.lbr / MLOAD14.AZM / MLOAD14.ASM
Encoding:
Assembly Source File  |  1993-10-26  |  27.0 KB  |  1,040 lines

  1.     TITLE    'MLOAD MULTI-FILE HEX LOAD UTILITY'
  2. ;
  3. ;         *********************************
  4. ;        *          MLOAD.ASM        *
  5. ;        *   MULTI-FILE HEX LOAD UTILITY *
  6. ;        *          FOR CP/M        *
  7. ;        *********************************
  8. ;
  9. ;            REV 1.4
  10. ;            05/29/83
  11. ;
  12. ;
  13. ; MODIFICATION HISTORY:
  14. ;
  15. ; 1.4   (RGF)    REPAIRED BUG WHICH SHOWED UP AS IMPROPER FILE
  16. ;        LOADING IF "N:<FILENAME>" SPECIFIED (I.E., THE
  17. ;        INPUT DRIVE IS NOT THE DEFAULT DRIVE).  MODIFIED
  18. ;        TO ALLOW THE OUTPUT FILE TYPE TO BE SPECIFIED.
  19. ;        (THE STRING AT "OUTTYP" IS NOW THE DEFAULT, RATHER
  20. ;        THAN THE FORCED, FILETYPE).  A NEW SYNTAX PARSING
  21. ;        OPTION ALLOWS COMMAND LINES OF THE FORM
  22. ;                D:=<FILENAME>
  23. ;        WHICH SENDS THE OUTPUT FILE TO DRIVE D.  FINALLY,
  24. ;        THE OUTPUT FILE NOW ALWAYS LANDS ON THE DEFAULT
  25. ;        DRIVE, UNLESS SPECIFICALLY SPECIFIED OTHERWISE IN
  26. ;        THE COMMAND LINE.
  27. ;
  28. ; 1.3   (RGF)   "UN-CONCEALED" COPYRIGHT NOTICE.  I DON'T MIND
  29. ;        PEOPLE ENHANCING, OR FIXING BUGS IN, MY PROGRAMS.
  30. ;        WHAT I *DO* MIND, HOWEVER, IS TAMPERING WITH
  31. ;        THE AUTHOR'S NAME (HIS STOCK IN TRADE).  MY INTENT
  32. ;           WAS THAT THE DISTRIBUTION VERSION SIGN ON WITH MY
  33. ;        COPYRIGHT NOTICE -- I DON'T CARE (NOR CAN I CONTROL)
  34. ;        WHAT MODS A USER MAKES TO HIS OWN VERSION OF THE
  35. ;        PROGRAM, BUT I MUST INSIST THAT THE DISTRIBUTION
  36. ;        VERSION CARRY MY COPYRIGHT NOTICE EXACTLY IN THE
  37. ;        WAY I ORIGINALLY INTENDED.
  38. ;                        --RON FOWLER
  39. ;                           05/11/83
  40. ;
  41. ; 1.2    (FJG)    FIXED STACK BUG WHEN LOADING LARGE HEX FILES. 
  42. ;        MODIFIED HEXOUT ROUTINE TO USE DAA INSTRUCTION.
  43. ;        CONCEALED COPYRIGHT NOTICE.
  44. ;
  45. ; 1.1    (RGF)    ADDED WARNING MSG IF FILE LOAD NOT AT 100H (THIS
  46. ;        IS TO ALERT THE USER WHO HAS INADVERTANTLY LEFT
  47. ;        OUT AN 'ORG 100H' FROM THE SOURCE FILE, AND SHOULD
  48. ;        BE IGNORED IF THE LOAD ADDRESS IS PURPOSELY NOT
  49. ;        100H). FIXED MINOR BUG WITH ONE OF THE ERROR MSGS.
  50. ;
  51. ; 1.0    (RGF)    ORIGINALLY WRITTEN BY RON FOWLER, FORT ATKINSON, WISCONSIN
  52. ;
  53. ;
  54. ;
  55. ; FOR ASSEMBLY WITH ASM.COM OR MAC (DELETE ABOVE TITLE LINE IF
  56. ; ASSEMBLING WITH ASM.COM)
  57. ;
  58. ; THIS PROGRAM IS A REPLACEMENT FOR THE CP/M "LOAD" PROGRAM.
  59. ; WHY REPLACE "LOAD"?  WELL... LOAD.COM HAS A FEW DEFICIENCIES.
  60. ; FOR EXAMPLE, IF YOUR HEX FILE'S ORIGIN IS ABOVE 100H, LOAD.COM
  61. ; PREPENDS BLANK SPACE TO THE OUTPUT FILE TO INSURE IT WILL WORK
  62. ; AS A CP/M TRANSIENT.  IT CARES NOT IF THE FILE IS NOT INTENDED
  63. ; AS A CP/M TRANSIENT.  IT ALSO DOESN'T LIKE HEX RECORDS WITH MIXED
  64. ; LOAD ADDRESSES  (FOR EXAMPLE, ONE THAT LOADS BELOW A PREVIOUS RECORD --
  65. ; WHICH IS A PERFECTLY LEGITIMATE HAPPENSTANCE).  ALSO, LOAD.COM
  66. ; CAN LOAD ONLY ONE PROGRAM AT A TIME, AND HAS NO PROVISION FOR
  67. ; A LOAD BIAS IN THE COMMAND SPECIFICATION. FINALLY, THERE IS NO
  68. ; PROVISION FOR USER SPECIFICATION OF OUTPUT FILE NAME.
  69. ;
  70. ;
  71. ; HENCE, THIS PROGRAM....
  72. ;
  73. ;------------------------------------------------------------
  74. ;
  75. ; SYNTAX IS AS FOLLOWS:
  76. ;
  77. ;    MLOAD [<OUTNAM=] <FILENAME>[,<FILENAME>...] [BIAS]
  78. ;
  79. ; WHERE <OUTNAM IS THE (OPTIONAL!;) OUTPUT FILE NAME (ONLY THE DRIVE
  80. ; SPEC AND PRIMARY FILENAME MAY BE SPECIFIED; THE OUTPUT FILETYPE IS
  81. ; DERIVED EXCLUSIVELY FROM THE 3-BYTE STRING AT 103H WITHIN MLOAD),
  82. ; <FILENAME> SPECIFIES FILES TO LOAD AND <BIAS> IS THE OFFSET WITHIN
  83. ; THE SAVED IMAGE TO APPLY WHEN LOADING THE FILE.
  84. ;
  85. ; MLOAD WITH NO ARGUMENTS PRINTS A SMALL HELP MESSAGE -- THIS MESSAGE
  86. ; IS ALSO PRINTED WHENEVER A COMMAND LINE SYNTAX ERROR OCCURS.
  87. ;
  88. ; FILENAMES MAY CONTAIN DRIVE SPECS, AND MUST NOT CONTAIN WILDCARDS.
  89. ; INPUT FILENAMES MUST BE SEPARATED BY COMMAS, AND A SPACE IS REQUIRED
  90. ; BETWEEN THE LAST FILENAME AND THE OPTIONAL BIAS.
  91. ;
  92. ; A LOAD INFORMATION SUMMARY IS PRINTED AT THE SUCCESSFUL CONCLUSION
  93. ; OF THE LOAD.  ANY ERRORS IN LOADING WILL GENERALLY INCLUDE THE NAME
  94. ; OF THE FILE IN QUESTION.
  95. ;
  96. ; IF NO OUTPUT FILENAME IS SPECIFIED, IT WILL BE DERIVED FROM THE FIRST
  97. ; INPUT FILENAME, WITH FILETYPE OF 'COM', IF NOT OTHERWISE SPECIFIED
  98. ; (THIS DEFAULT FILETYPE MAY BE PATCHED DIRECTLY INTO MLOAD VIA DDT
  99. ; -- ITS LOCATION IS AT 103H IN MLOAD.COM). NOTE THAT A COMMAND LINE OF
  100. ; THE FORM "C:=<FILENAME>" WILL PLACE THE OUTPUT FILE ON THE "C" DRIVE
  101. ; WITH THE SAME PRIMARY FILENAME AS THE INPUT FILE.
  102. ;
  103. ; IN ITS SIMPLEST FORM, MLOAD'S SYNTAX IS IDENTICAL TO LOAD.COM; THUS
  104. ; THERE SHOULD BE NO PROBLEM IN LEARNING TO USE THE NEW PROGRAM.  THE
  105. ; ONLY SIGNIFICANT DIFFERENCE HERE IS THAT, UNDER LOAD.COM, ALL FILES
  106. ; ARE OUTPUT STARTING AT 100H, EVEN IF THEY ORIGINATE ELSEWHERE.  MLOAD
  107. ; OUTPUTS STARTING AT THE HEX FILE ORIGIN (ACTUALLY, THE FIRST HEXT REC-
  108. ; ORD SPECIFIES THE OUTPUT LOAD ADDRESS).  THE BIAS OPTION MAY BE USED
  109. ; TO OVERRIDE THIS.
  110. ;
  111. ; AN EXAMPLE SHOULD CLARIFY THIS.  SUPPOSE YOU HAVE A FILE THAT LOADS
  112. ; AT 1000H.  LOAD.COM WOULD SAVE AN OUTPUT FILE THAT BEGINS AT 100H AND
  113. ; LOADS PAST 1000H (TO WHEREVER THE PROGRAM ENDS).  MLOAD WILL SAVE AN
  114. ; OUTPUT FILE STARTING FROM 1000H ONLY.  IF, FOR SOME REASON YOU NEED THE
  115. ; FILE TO START AT 100H IN SPITE OF ITS 1000H ORIGIN (I CAN THINK OF SEV-
  116. ; ERAL CIRCUMSTANCES WHERE THIS WOULD BE NECESSARY), YOU'D HAVE TO SPECIFY
  117. ; A BIAS TO MLOAD.  THUS, USING THIS EXAMPLE, "MLOAD MYFILE 0F00" WOULD DO.
  118. ;
  119. ; NOTE THAT THIS PROGRAM RE-INITIALIZES ITSELF EACH TIME IT IS RUN.
  120. ; THUS, IF YOUR SYSTEM SUPPORTS A DIRECT BRANCH TO THE TPA (VIA A ZERO-LENGTH
  121. ; .COM FILE, OR THE ZCPR "GO" COMMAND), YOU MAY SAFELY RE-EXECUTE MLOAD.
  122. ;
  123. ; PLEASE REPORT ANY BUGS, BUG FIXES, OR ENHANCEMENTS TO ME AT:
  124. ;
  125. ;        "FORT FONE FILE FOLDER" RCPM/CBBS
  126. ;        (414) 563-9932 (NO RING BACK)
  127. ;
  128. ;                --RON FOWLER
  129. ;                  02/21/83
  130. ;------------------------------------------------------------
  131. ;
  132. ; CP/M EQUATES
  133. ;
  134. WARMBT    EQU    0        ;WARM BOOT
  135. BDOS    EQU    5        ;SYSTEM ENTRY (ALSO TOP OF MEM PNTR)
  136. DFCB    EQU    5CH        ;DEFAULT FILE CONTROL BLOCK
  137. FT    EQU    9        ;FCB OFFSET TO FILETYPE
  138. TBUF    EQU    80H        ;DEFAULT BUFFER
  139. TPA    EQU    100H        ;TRANSIENT PROGRAM AREA
  140. EOF    EQU    1AH        ;CP/M END-OF-FILE MARK
  141. FCBSIZ    EQU    33        ;SIZE OF FILE CONTROL BLOCK
  142. ;
  143. ; CP/M SYSTEM CALLS
  144. ;
  145. PCHARF    EQU    2        ;PRINT CHAR
  146. OPENF    EQU    15        ;OPEN FILE
  147. CLOSEF    EQU    16        ;CLOSE FILE
  148. ERASEF    EQU    19        ;DELETE FILE
  149. READF    EQU    20        ;READ RECORD
  150. WRITEF    EQU    21        ;WRITE RECORD
  151. CREATF    EQU    22        ;CREATE FILE
  152. GETDRF    EQU    25        ;RETURN DFLT DRIVE #
  153. SDMAF    EQU    26        ;SET DMA ADDRESS
  154. ;
  155. ; MISCELLANEOUS EQUATES
  156. ;
  157. CR    EQU    13
  158. LF    EQU    10
  159. BEL    EQU    7
  160. ;
  161. ; WITHOUT FURTHER ADO...
  162. ;
  163.     ORG    TPA
  164. ;
  165.     JMP    BEGIN        ;JUMP OVER DEFAULT OUTPUT FILETYPE
  166. ;
  167. ; THE OUTPUT FILETYPE IS LOCATED AT 103H FOR EASY PATCHING WITH DDT
  168. ;
  169. OUTTYP:    DB    'COM'
  170. ;
  171. BEGIN:    LXI    H,0        ;SAVE SYSTEM STACKPOINTER
  172.     DAD    SP
  173.     SHLD    SPSAVE
  174.     LXI    SP,STACK    ;LOAD LOCAL STACK
  175.     CALL    ILPRNT        ;SIGN ON
  176.     DB    'MLOAD ver. 1.4   Copyright (C) 1983 Ronald G. Fowler'
  177.     DB    CR,LF,0
  178.     CALL    SETUP        ;INITIALIZE
  179. MAIN:    CALL    NXTFIL        ;PARSE AND READ NEXT INPUT FILE
  180.     JC    DONE        ;NO MORE...
  181.     CALL    LODFIL        ;YEP, LOAD IT
  182.     CALL    CLOSFL        ;CLOSE IT (IN CASE MP/M)
  183.     JMP    MAIN        ;MAYBE MORE
  184. DONE:    CALL    WRTFIL        ;WRITE THE OUTPUT FILE
  185. ;
  186. ; EXIT TO CP/M
  187. ;
  188. EXIT:    LXI    D,TBUF        ;RESTORE DMA ADDRESS
  189.     MVI    C,SDMAF
  190.     CALL    BDOS
  191.     LDA    BDOS+2        ;GET TOP OF MEMORY POINTER
  192.     SUI    9        ;ALLOW FOR CCP+SLOP
  193.     LXI    H,HILOAD+1    ;HIGHEST LOAD ADDRESS
  194.     SUB    M        ;ABOVE CCP?
  195.     JC    WARMBT        ;THEN WARM-BOOT
  196.     LHLD    SPSAVE        ;NOPE, CCP STILL IN MEMORY
  197.     SPHL            ;RESTORE ITS STACK
  198.     RET            ;RETURN TO CCP
  199. ;
  200. ; LOAD PROGRAM INITIALIZATION
  201. ;
  202. SETUP:    XRA    A        ;GET A ZERO IN A
  203.     STA    LODFLG        ;FLAG NO FILES LOADED YET
  204.     STA    BUFPTR        ;FORCE A DISK READ
  205.     LXI    H,OUTNAM    ;SET OUTPUT NAME DR FIELD DEFAULT DRV
  206.     MOV    M,A        ;ZERO TYPE
  207.     INX    H
  208.     MVI    B,11        ;BLANK NAME
  209. CLOFN:    MVI    M,' '
  210.     INX    H        ;INIT OUTPUT NAME
  211.     DCR    B
  212.     JNZ    CLOFN
  213.     MVI    M,' '        ;INIT OUTPUT NAME TO NULL
  214.     LXI    H,0        ;NO BIAS YET
  215.     SHLD    BIAS
  216.     SHLD    RECCNT        ;NO RECORDS WRITTEN YET
  217.     SHLD    BYTCNT        ;NO BYTES LOADED YET
  218.     LXI    H,CMDBUF    ;GET POINTER TO COMMAND BUFFER
  219.     SHLD    CMDPTR        ;SAVE
  220.     XCHG            ;CMDBUF IN DE
  221.     LXI    H,TBUF        ;POINT TO COMMAND TAIL BUFR
  222.     MOV    A,M        ;GET ITS LENGTH
  223.     INX    H
  224.     ORA    A        ;DOES IT HAVE ANY LENGTH?
  225.     JZ    HELP        ;NOPE, GO GIVE USAGE HELP
  226.     MOV    B,A        ;YEP, GET LENGTH TO B
  227.     CALL    MOVE        ;MOVE CMD TAIL TO BUFFER
  228.     XCHG            ;END OF DEST TO HL
  229.     MVI    M,0        ;STUFF A TERMINATOR
  230.     INX    H        ;POINT TO FIRST FREE MEMORY
  231.     SHLD    FILBUF        ;SET UP FILE BUFFER
  232.     XCHG            ;FILE BUFR ADRS TO DE
  233.     LHLD    BDOS+1        ;GET TOP OF MEMORY POINTER
  234.     MOV    A,L        ;COMPUTE SIZE OF FILE BUFFER
  235.     SUB    E
  236.     MOV    C,A        ;WITH RESULT IN BC
  237.     MOV    A,H
  238.     SUI    9        ;ALLOW FOR CCP
  239.     SBB    D
  240.     MOV    B,A
  241.     XCHG            ;BUFFER POINTER TO HL
  242. NITMEM:    MVI    M,0        ;CLEAR BUFFER
  243.     INX    H
  244.     DCX    B
  245.     MOV    A,B
  246.     ORA    C
  247.     JNZ    NITMEM
  248.     LXI    H,CMDBUF-1    ;POINT TO COMMAND BUFFER
  249.     CALL    SCANBK        ;SCAN PAST BLANKS
  250.     ORA    A        ;NO NON-BLANK CHARS?
  251.     JZ    HELP        ;THEN GO PRINT HELP TEXT
  252. FNDSPC:    INX    H        ;POINT TO NEXT
  253.     MOV    A,M        ;FETCH IT
  254.     ORA    A        ;TEST IT
  255.     RZ            ;LINE ENDED, RETURN
  256.     CPI    ' '        ;NOPE, TEST FOR BLANK
  257.     JNZ    FNDSPC        ;NOT BLANK, CONTINUE
  258.     CALL    SCANBK        ;SKIP BLANKS
  259.     ORA    A        ;END-OF-LINE?
  260.     RZ            ;RETURN IF SO
  261. ;
  262. ; HL POINTS TO BIAS IN COMMAND LINE
  263. ;
  264.     LXI    D,0        ;INIT BIAS
  265.     CALL    HEXDIG        ;INSURE A HEX DIGIT
  266.     JC    SYNERR        ;BAD...
  267. HEXLP:    MOV    A,M        ;NO.  GET NEXT CHAR
  268.     INX    H        ;SKIP OVER IT
  269.     CALL    HEXDIG        ;TEST FOR HEX DIGIT
  270.     JNC    DIGOK        ;JUMP IF GOOD HEX DIGIT
  271.     ORA    A        ;MUST END ON NULL TERMINATOR
  272.     JNZ    SYNERR
  273.     XCHG            ;GOOD END, GET BIAS TO HL
  274.     SHLD    BIAS        ;STUFF IT
  275.     RET            ;DONE
  276. DIGOK:    XCHG            ;BIAS TO HL
  277.     DAD    H        ;SKIFT LEFT 4 TO MAKE ROOM
  278.     DAD    H        ;   FOR NEW HEX DIGIT
  279.     DAD    H
  280.     DAD    H
  281.     XCHG            ;BACK TO DE
  282.     ADD    E        ;ADD IN NEW DIGIT
  283.     MOV    E,A
  284.     JNC    HEXLP        ;JUMP IF NO 8-BIT OVFL
  285.     INR    D        ;CARRY
  286.     JMP    HEXLP
  287. ;
  288. ; SET UP NEXT INPUT FILE
  289. ;
  290. NXTFIL:    LHLD    CMDPTR        ;GET COMMAND LINE POINTER
  291. NEXT2:    LXI    D,DFCB        ;DESTINATION FCB
  292.     CALL    FPARSE        ;PARSE A FILENAME
  293.     CPI    '='        ;OUTPUT SPECIFIER?
  294.     JNZ    NOTEQ
  295.     LDA    OUTNAM+1    ;INSURE NO NAME YET SPECIFIED
  296.     CPI    ' '
  297.     JNZ    SYNERR        ;SYNTAX ERROR IF SPECIFIED TWICE
  298.     INR    B        ;INSURE NO AMBIGUOUS OUTPUT NAME
  299.     DCR    B
  300.     JNZ    AFNERR
  301.     INX    H        ;SKIP OVER '='
  302.     PUSH    H        ;SAVE CMD LINE POINTER
  303.     LXI    H,DFCB        ;MOVE THE NAME TO OUTPUT NAME HOLD
  304.     LXI    D,OUTNAM
  305.     MVI    B,12        ;DRIVE SPEC TOO
  306.     CALL    MOVE
  307.     POP    H        ;RESTORE COMMAND LINE POINTER
  308.     JMP    NEXT2        ;GO PARSE ANOTHER
  309. NOTEQ:    CPI    ','        ;STOPPED ON COMMA?
  310.     JZ    GCOMMA        ;JUMP IF SO
  311.     MVI    M,0        ;NOPE, INSURE END OF INPUT
  312.     JMP    NXT2        ;DON'T ADVANCE OVER FAKE END
  313. GCOMMA:    INX    H        ;SKIP OVER COMMA
  314. NXT2:    SHLD    CMDPTR        ;SAVE NEW COMMAND LINE PNTR
  315.     MOV    A,B        ;GET AMBIG CHAR COUNT
  316.     ORA    A        ;TEST IT
  317.     JNZ    AFNERR        ;ALLOW NO AMBIG CHARACTERS
  318.     STA    BUFPTR        ;FORCE A DISK READ
  319.     LXI    D,DFCB+1    ;LOOK AT PARSED FILENAME
  320.     LDAX    D
  321.     CPI    ' '        ;BLANK? (INPUT ENDED?)
  322.     STC            ;GET CARRY READY IN CASE SO
  323.     RZ            ;RETURN CY IF INPUT GONE
  324.     DCX    D        ;NOPE, POINT DE TO START OF FCB
  325.     LXI    H,DFCB+FT    ;POINT TO FILE TYPE
  326.     MOV    A,M        ;ANYTHING THERE?
  327.     CPI    ' '
  328.     JNZ    OPENIT        ;JUMP IF SO
  329.     MVI    M,'H'        ;NOPE, FILL IN 'HEX'
  330.     INX    H
  331.     MVI    M,'E'
  332.     INX    H
  333.     MVI    M,'X'
  334. OPENIT:    MVI    C,OPENF        ;OPEN THE FILE
  335.     CALL    BDOS
  336.     INR    A        ;DID IT OPEN OK?
  337.     JZ    FNFERR        ;OOPS...
  338.     XRA    A        ;YEP, RESET CY ("INR A" IGNORES CARRY)
  339.     RET
  340. ;
  341. ; LOAD CURRENT FILE
  342. ;
  343. LODFIL:    LHLD    BIAS        ;GET BIAS ON TOP OF STACK
  344.     PUSH    H
  345. ;
  346. ; LOAD A HEX RECORD
  347. ;
  348. LOADLP:    CALL    GNB        ;GET NEXT FILE BYTE
  349.     SBI    ':'        ;LOOK FOR START-RECORD MARK
  350.     JNZ    LOADLP        ;SCAN UNTIL FOUND
  351.     STA    CKSUM        ;GOT IT, INIT CHECKSUM TO ZERO
  352.     MOV    D,A        ;UPPER BYTE OF REC CNT=0
  353.     POP    B        ;RETRIEVE BIAS ADRS
  354.     PUSH    B        ;SAVE IT AGAIN
  355.     CALL    GHBCKS        ;GET HEX BYTE W/CHECKSUM
  356.     MOV    E,A        ;DE NOW HAS RECORD LENGTH
  357.     ORA    A        ;TEST IT
  358.     JNZ    NOTEND        ;JUMP IF LEN<>0 (NOT EOF REC)
  359.     POP    H        ;ALL DONE
  360.     RET
  361. NOTEND:    CALL    GHBCKS        ;HI BYTE OF REC LD ADRS
  362.     MOV    H,A        ;ACCUMULATE IN HL
  363.     CALL    GHBCKS        ;GET LO BYTE
  364.     MOV    L,A        ;PUT LO IN L
  365.     LDA    LODFLG        ;TEST LOAD FLAG
  366.     ORA    A
  367.     JNZ    SKPNIT        ;NOT FIRST RECORD, JUMP
  368.     MVI    A,1        ;FIRST RECORD, SET LOAD FLAG
  369.     STA    LODFLG
  370.     SHLD    LODADR        ;SAVE LOAD ADDRESS
  371.     SHLD    HIPC        ;AND HI LOAD
  372.     PUSH    D        ;SAVE RECORD LENGTH
  373.     XCHG            ;DE=LOAD ADDRESS
  374.     LHLD    FILBUF        ;GET ADDRESS OF FILE BUFFER
  375.     MOV    A,L        ;SUBTRACT LOAD ADRS FROM FILE BUFFER
  376.     SUB    E
  377.     MOV    L,A
  378.     MOV    A,H
  379.     SBB    D
  380.     MOV    H,A
  381.     SHLD    OFFSET        ;SAVE AS LOAD OFFSET
  382.     PUSH    D        ;SAVE LOAD ADDRESS ON STACK
  383.     PUSH    B        ;SAVE BIAS
  384.     LXI    D,OUTNAM+1    ;CHECK OUTPUT FILENAME
  385.     LDAX    D        ;(FIRST CHAR)
  386.     CPI    ' '
  387.     JNZ    NAMSKP        ;JUMP IF SO
  388.     LXI    H,DFCB+1    ;GET FIRST NAME POINTER
  389.     MVI    B,8        ;(DON'T INCLUDE DRIVE SPEC)
  390.     CALL    MOVE
  391. NAMSKP:    POP    B        ;RESTORE BIAS
  392.     POP    H        ;LOAD ADDRESS TO HL
  393.     POP    D        ;RESTORE RECORD LENGTH
  394. SKPNIT:    PUSH    H        ;SAVE LOAD ADDRESS
  395.     DAD    D        ;ADD IN RECORD LENGTH
  396.     DCX    H        ;MAKE HIGHEST, NOT NEXT
  397.     LDA    HIPC        ;A NEW HIGH?
  398.     SUB    L
  399.     LDA    HIPC+1
  400.     SBB    H
  401.     JNC    NOTGT        ;JUMP IF NOT
  402.     SHLD    HIPC        ;YEP, UPDATE HIPC
  403.     PUSH    D        ;SAVE RECLEN
  404.     XCHG            ;LOAD ADRS TO DE
  405.     LHLD    OFFSET        ;GET OFFSET TO FORM TRUE MEMORY ADRS
  406.     DAD    D        ;ADD IN OFFSET
  407.     DAD    B        ;AND BIAS
  408.     SHLD    HILOAD        ;MARK HIGHEST TRUE MEMORY LOAD ADRS
  409.     LDA    BDOS+2        ;VALIDATE AGAINST TOP-MEM POINTER
  410.     CMP    H
  411.     JC    MEMFUL        ;JUMP IF OUT OF MEMORY
  412.     POP    D        ;RESTORE RECLEN
  413. NOTGT:    POP    H        ;RESTORE LOAD ADDRESS
  414.     DAD    B        ;ADD BIAS TO LOAD ADRS
  415.     PUSH    D        ;SAVE RECORD LENGTH
  416.     PUSH    H
  417.     LHLD    BYTCNT        ;ADD RECORD LENGTH TO BYTE COUNT
  418.     DAD    D
  419.     SHLD    BYTCNT
  420.     POP    H
  421.     XCHG
  422.     LHLD    OFFSET        ;CALCULATE TRUE MEMORY ADRS
  423.     DAD    D        ;HL=TRUE LOADING ADRS
  424.     POP    D        ;RESTORE RECORD LENGTH
  425.     CALL    GHBCKS        ;SKIP UNUSED BYTE OF INTEL FORMAT
  426. ;
  427. ; MOVE THE RECORD INTO MEMORY
  428. ;
  429. RECLP:    CALL    GHBCKS        ;GET HEX BYTE
  430.     MOV    M,A        ;STORE IT IN BUFFER
  431.     INX    H        ;POINT TO NEXT
  432.     DCR    E        ;COUNT DOWN
  433.     JNZ    RECLP        ;UNTIL RECORD ALL READ
  434.     CALL    GHBCKS        ;GET CHECKSUM BYTE
  435.     JNZ    CSERR        ;FINAL ADD CKSUM SHOULD SUM 0
  436.     JMP    LOADLP        ;GOOD LOAD, GO DO NXT RECORD
  437. ;
  438. ; GET NEXT HEX BYTE FROM INPUT, AND
  439. ; ACCUMULATE A CHECKSUM
  440. ;
  441. GHBCKS: PUSH    B        ;SAVE EM ALL
  442.     PUSH    H
  443.     PUSH    D
  444.     CALL    HEXIN        ;GET HEX BYTE
  445.     MOV    B,A        ;SAVE IN B
  446.     LXI    H,CKSUM        ;ADD TO CHECKSUM
  447.     MOV    A,M
  448.     ADD    B
  449.     MOV    M,A
  450.     MOV    A,B        ;GET BYTE BACK
  451.     POP    D        ;RESTORE CHECKSUM
  452.     POP    H        ;RESTORE OTHER REGS
  453.     POP    B
  454.     RET
  455. ;
  456. ; ROUTINE TO GET NEXT BYTE FROM INPUT...FORMS
  457. ; BYTE FROM TWO ASCII HEX CHARACTERS
  458. ;
  459. HEXIN:    CALL    GNB        ;GET NEXT INPUT FILE BYTE
  460.     CALL    HEXVAL        ;CONVERT TO BINARY W/VALIDATION
  461.     RLC            ;MOVE INTO MS NYBBLE
  462.     RLC
  463.     RLC
  464.     RLC
  465.     ANI    0F0H        ;KILL POSSIBLE GARBAGE
  466.     PUSH    PSW        ;SAVE IT
  467.     CALL    GNB        ;GET NEXT BYTE
  468.     CALL    HEXVAL        ;CONVERT IT, W/VALIDATION
  469.     POP    B        ;GET BACK FIRST
  470.     ORA    B        ;OR IN SECOND
  471.     RET            ;GOOD BYTE IN A
  472. ;
  473. ; GNB - UTILITY SUBROUTINE TO GET NEXT
  474. ;    BYTE FROM DISK FILE
  475. GNB:    PUSH    H        ;SAVE ALL REGS
  476.     PUSH    D
  477.     PUSH    B
  478.     LDA    BUFPTR        ;GET INPUT BUFR POINTER
  479.     ANI    7FH        ;WOUND BACK TO 0?
  480.     JZ    DISKRD        ;GO READ SECTOR IF SO
  481. GNB1:    MVI    D,0        ;ELSE FORM 16 BIT OFFSET
  482.     MOV    E,A
  483.     LXI    H,TBUF        ;FROM TBUF
  484.     DAD    D        ;ADD IN OFFSET
  485.     MOV    A,M        ;GET NEXT BYTE
  486.     CPI    EOF        ;END OF FILE?
  487.     JZ    EOFERR        ;ERROR IF SO
  488.     LXI    H,BUFPTR     ;ELSE BUMP BUF PTR
  489.     INR    M
  490.     ORA    A        ;RETURN CARRY CLEAR
  491.     POP    B        ;RESTORE AND RETURN
  492.     POP    D
  493.     POP    H
  494.     RET
  495. ;
  496. ; READ NEXT SECTOR FROM DISK
  497. ;
  498. DISKRD: MVI    C,READF        ;BDOS "READ SEC" FUNCTION
  499.     LXI    D,DFCB
  500.     CALL    BDOS        ;READ SECTOR
  501.     ORA    A
  502.     JNZ    EOFERR        ;ERROR IF PHYS END OF FILE
  503.     STA    BUFPTR        ;STORE 0 AS NEW BUF PTR
  504.     JMP    GNB1        ;GO RE-JOIN GNB CODE
  505. ;
  506. ; WRITE OUTPUT FILE
  507. ;
  508. WRTFIL:    LXI    D,DFCB        ;POINT TO FCB
  509.     PUSH    D        ;SAVE 2 COPIES OF POINTER
  510.     PUSH    D
  511.     CALL    NITFCB        ;INITIALIZE OUTPUT FCB
  512.     LXI    H,OUTNAM    ;MOVE OUTPUT NAME IN
  513.     MVI    B,9
  514.     CALL    MOVE
  515.     MOV    A,M        ;OUTPUT TYPE BLANK?
  516.     CPI    ' '
  517.     JNZ    WRTNB        ;JUMP IF NOT
  518.     LXI    H,OUTTYP    ;YES, MOVE DFLT OUTPUT FILETYPE IN
  519. WRTNB:    MVI    B,3
  520.     CALL    MOVE
  521.     POP    D        ;RESTORE FCB POINTER
  522.     MVI    C,ERASEF    ;ERASE ANY EXISTING FILE
  523.     CALL    BDOS
  524.     POP    D        ;RESTORE FCB POINTER
  525.     MVI    C,CREATF    ;CREATE A NEW FILE
  526.     CALL    BDOS
  527.     INR    A        ;GOOD CREATE?
  528.     JZ    DIRFUL        ;GOTO DIRECTORY FULL ERROR IF NOT
  529.     LHLD    HILOAD        ;YEP, GET TOP OF BUFR PNTR
  530.     XCHG            ;IN DE
  531.     LHLD    FILBUF        ;GET START OF BUFR ADRS
  532.     MOV    A,E        ;CALCULATE OUTPUT FILE SIZE
  533.     SUB    L
  534.     MOV    C,A        ;WITH RESULT IN BC
  535.     MOV    A,D
  536.     SBB    H
  537.     MOV    B,A
  538.     MOV    A,B        ;TEST LENGTH
  539.     ORA    C
  540.     JZ    LODERR        ;NOTHING TO WRITE???
  541.     LXI    D,DFCB        ;GET FCB POINTER
  542. WRLP:    PUSH    B        ;SAVE COUNT
  543.     PUSH    D        ;AND FCB POINTER
  544.     XCHG            ;GET MEMORY POINTER TO DE
  545.     LXI    H,128        ;ADD IN SECTOR LENGTH FOR NEXT PASS
  546.     DAD    D
  547.     XTHL            ;SAVE NEXT DMA
  548.     PUSH    H        ;ABOVE FCB
  549.     MVI    C,SDMAF        ;SET TRANSFER ADDRESS
  550.     CALL    BDOS
  551.     POP    D        ;FETCH FCB POINTER
  552.     PUSH    D        ;SAVE IT AGAIN
  553.     MVI    C,WRITEF    ;WRITE A SECTOR
  554.     CALL    BDOS
  555.     INR    A        ;TEST RESULT
  556.     JZ    DSKFUL        ;DISK FULL ERROR...
  557.     LHLD    RECCNT        ;NO,INCREMENT COUNT OF RECORDS
  558.     INX    H
  559.     SHLD    RECCNT
  560.     POP    D        ;RESTORE FCB POINTER
  561.     POP    H        ;AND MEMORY WRITE POINTER
  562.     POP    B        ;AND COUNT
  563.     MOV    A,C        ;SUBTRACT 128 (SEC SIZE) FROM COUNT
  564.     SUI    128
  565.     MOV    C,A
  566.     JNC    WRLP        ;JUMP IF SOME LEFT
  567.     MOV    A,B        ;HI-ORDER BORROW
  568.     SUI    1        ;DO IT
  569.     MOV    B,A        ;RESTORE
  570.     JNC    WRLP        ;JUMP IF MORE LEFT
  571.     CALL    CLOSFL        ;CLOSE OUTPUT FILE
  572. ;
  573. ; REPORT STATISTICS TO CONSOLE
  574. ;
  575.     CALL    ILPRNT
  576.     DB    'Loaded ',0
  577.     LHLD    BYTCNT        ;PRINT # BYTES
  578.     CALL    DECOUT
  579.     CALL    ILPRNT
  580.     DB    ' bytes (',0
  581.     LHLD    BYTCNT        ;ALSO PRINT IN HEX
  582.     CALL    HEXOUT
  583.     CALL    ILPRNT
  584.     DB    'H - ',0
  585.     LHLD    RECCNT        ;PRINT # RECORDS
  586.     CALL    DECOUT
  587.     CALL    ILPRNT
  588.     DB    ' records) to file %'
  589.     DB    CR,LF,'Start address: ',0
  590.     LHLD    LODADR        ;PRINT LOADING ADDRESS
  591.     CALL    HEXOUT
  592.     CALL    ILPRNT
  593.     DB    'H  Ending address: ',0
  594.     LHLD    HIPC        ;PRINT ENDING LOAD ADDRESS
  595.     CALL    HEXOUT
  596.     CALL    ILPRNT
  597.     DB    'H  Bias: ',0
  598.     LHLD    BIAS
  599.     CALL    HEXOUT
  600.     CALL    ILPRNT
  601.     DB    'H',CR,LF,0
  602.     LHLD    LODADR        ;FETCH LOADING ADDRESS
  603.     MOV    A,L        ;TEST IF =TPA
  604.     ORA    A
  605.     JNZ    NOTTPA        ;TPA ALWAYS ON PAGE BOUNDARY
  606.     MOV    A,H        ;LO OK, TEST HI
  607.     CPI    (TPA SHR 8) AND 0FFH
  608.     RZ            ;RETURN IF TPA
  609. NOTTPA:    CALL    ILPRNT        ;NOT, SO PRINT WARNING MSG
  610.     DB    CR,LF,BEL
  611.     DB    '++ Warning: program origin NOT at 100H ++'
  612.     DB    CR,LF,0
  613.     RET            ;DONE
  614. ;
  615. ;    ***********************
  616. ;    * UTILITY SUBROUTINES *
  617. ;    ***********************
  618. ;
  619. ;
  620. ; ROUTINE TO CLOSE ANY OPEN FILE
  621. ;
  622. CLOSFL:    LXI    D,DFCB
  623.     MVI    C,CLOSEF
  624.     CALL    BDOS
  625.     INR    A        ;TEST CLOSE RESULT
  626.     JZ    CLSERR        ;JUMP IF ERROR
  627.     RET
  628. ;
  629. ; PRINT MESSAGE IN-LINE WITH CODE
  630. ;
  631. ILPRNT:    XTHL            ;MESSAGE PNTR TO HL
  632.     CALL    PRATHL        ;PRINT IT
  633.     XTHL            ;RESTORE AND RETURN
  634.     RET
  635. ;
  636. ; PRINT MSG POINTED TO BY HL UNTIL NULL.  EXPAND
  637. ; '%' CHAR TO CURRENT FILENAME.
  638. ;
  639. PRATHL:    MOV    A,M        ;FETCH CHAR
  640.     INX    H        ;POINT TO NEXT
  641.     ORA    A        ;TERMINATOR?
  642.     RZ            ;THEN DONE
  643.     CPI    '%'        ;WANT FILENAME?
  644.     JZ    PRTFN        ;GO DO IT IF SO
  645.     CALL    TYPE        ;NOPE, JUST PRINT CHAR
  646.     JMP    PRATHL        ;CONTINUE
  647. ;
  648. PRTFN:    PUSH    H        ;SAVE POINTER
  649.     PUSH    B
  650.     LXI    H,DFCB        ;POINT TO DR FIELD OF DFCB
  651.     MOV    A,M        ;FETCH IT
  652.     INX    H        ;ADVANCE TO NAME FIELD
  653.     ORA    A        ;DEFAULT DRIVE?
  654.     JNZ    PRNDF        ;JUMP IF NOT
  655.     PUSH    H        ;YES, SAVE FCB POINTER
  656.     MVI    C,GETDRF    ;GET DFLT DRV #
  657.     CALL    BDOS
  658.     POP    H
  659.     INR    A        ;MAKE IT ONE-RELATIVE (AS IN FCB)
  660. PRNDF:    ADI    'A'-1        ;MAKE DRIVE NAME PRINTABLE
  661.     CALL    TYPE        ;PRINT IT
  662.     MVI    A,':'        ;DRIVE NAMES FOLLOWED BY COLON
  663.     CALL    TYPE
  664.     MVI    B,8        ;PRINT UP TO 8
  665.     CALL    PRTNAM
  666.     MVI    A,'.'        ;PRINT DOT
  667.     CALL    TYPE
  668.     MVI    B,3        ;PRINT FILETYPE FIELD
  669.     CALL    PRTNAM
  670.     POP    B
  671.     POP    H        ;RESTORE AND CONTINUE
  672.     JMP    PRATHL
  673. ;
  674. ; PRINT FILE NAME @HL MAX LENGTH IN B.  DON'T PRINT SPACES
  675. ;
  676. PRTNAM:    MOV    A,M        ;FETCH A CHAR
  677.     CPI    ' '        ;BLANK?
  678.     JZ    PWIND        ;GO WIND IF SO
  679.     INX    H        ;NOPE, MOVE TO NEXT
  680.     CALL    TYPE        ;PRINT IT
  681.     DCR    B        ;COUNT DOWN
  682.     JNZ    PRTNAM        ;CONTINUE
  683.     RET
  684. PWIND:    INX    H        ;SKIP REMAINDER OF BLANK NAME
  685.     DCR    B
  686.     JNZ    PWIND
  687.     RET
  688. ;
  689. ; PRINT HL IN DECIMAL ON CONSOLE
  690. ;
  691. DECOUT:    PUSH    H        ;SAVE EVERYBODY
  692.     PUSH    D
  693.     PUSH    B
  694.     LXI    B,-10        ;CONVERSION RADIX
  695.     LXI    D,-1
  696. DECLP:    DAD    B
  697.     INX    D
  698.     JC    DECLP
  699.     LXI    B,10
  700.     DAD    B
  701.     XCHG
  702.     MOV    A,H
  703.     ORA    L
  704.     CNZ    DECOUT        ;THIS IS RECURSIVE
  705.     MOV    A,E
  706.     ADI    '0'
  707.     CALL    TYPE
  708.     POP    B
  709.     POP    D
  710.     POP    H
  711.     RET
  712. ;
  713. ; NEWLINE ON CONSOLE
  714. ;
  715. CRLF:    MVI    A,CR
  716.     CALL    TYPE
  717.     MVI    A,LF
  718.     JMP    TYPE
  719. ;
  720. ; PRINT HL ON CONSOLE IN HEX
  721. ;
  722. HEXOUT:    MOV    A,H        ;GET HI
  723.     CALL    HEXBYT        ;PRINT IT
  724.     MOV    A,L        ;GET LO, FALL INTO HEXBYT
  725. ;
  726. ; TYPE ACCUMULATOR ON CONSOLE IN HEX
  727. ;
  728. HEXBYT: PUSH    PSW        ;SAVE BYTE
  729.     RAR            ;GET MS NYBBLE..
  730.     RAR            ;..INTO LO 4 BITS
  731.     RAR
  732.     RAR
  733.     CALL    NYBBLE
  734.     POP    PSW        ;GET BACK BYTE
  735. NYBBLE:    ANI    0FH        ;MASK MS NYBBLE
  736.     ADI    90H        ;ADD OFFSET
  737.     DAA            ;DECIMAL ADJUST A-REG
  738.     ACI    40H        ;ADD OFFSET
  739.     DAA            ;FALL INTO TYPE
  740. ;
  741. ; TYPE CHAR IN A ON CONSOLE
  742. ;
  743. TYPE:    PUSH    H        ;SAVE ALL
  744.     PUSH    D
  745.     PUSH    B
  746.     MOV    E,A        ;CP/M OUTPUTS FROM E
  747.     MVI    C,PCHARF
  748.     CALL    BDOS
  749.     POP    B
  750.     POP    D
  751.     POP    H
  752.     RET
  753. ;
  754. ; MOVE: FROM @HL TO @DE, COUNT IN B
  755. ;
  756. MOVE:    INR    B        ;UP ONE
  757. MOVLP:    DCR    B        ;COUNT DOWN
  758.     RZ            ;RETURN IF DONE
  759.     MOV    A,M        ;NOT DONE, CONTINUE
  760.     STAX    D
  761.     INX    H        ;POINTERS=POINTERS+1
  762.     INX    D
  763.     JMP    MOVLP
  764. ;
  765. ; SCAN TO FIRST NON-BLANK CHAR IN STRING @HL
  766. ;
  767. SCANBK:    INX    H        ;NEXT
  768.     MOV    A,M        ;FETCH IT
  769.     CPI    ' '
  770.     JZ    SCANBK
  771.     RET
  772. ;
  773. ; GET HEX DIGIT AND VALIDATE
  774. ;
  775. HEXVAL:    CALL    HEXDIG        ;GET HEX DIGIT
  776.     JC    FORMERR        ;JUMP IF BAD
  777.     RET
  778. ;
  779. ; GET HEX DIGIT, RETURN CY=1 IF BAD DIGIT
  780. ;
  781. HEXDIG:    CPI    '0'        ;LO BOUNDARY TEST
  782.     RC            ;BAD ALREADY?
  783.     CPI    '9'+1        ;NO, TEST HI
  784.     JC    HEXCVT        ;JUMP IF NUMERIC
  785.     CPI    'A'        ;TEST ALPHA
  786.     RC            ;BAD?
  787.     CPI    'F'+1        ;NO, UPPER ALPHA BOUND
  788.     CMC            ;PERVERT CARRY
  789.     RC            ;BAD?
  790.     SUI    7        ;NO, ADJUST TO 0-F
  791. HEXCVT:    ANI    0FH        ;MAKE IT BINARY
  792.     RET
  793. ;
  794. ;    ******************
  795. ;    * ERROR HANDLERS *
  796. ;    ******************
  797. ;
  798. SYNERR:    CALL    CRLF
  799.     CALL    ILPRNT
  800.     DB    '      Command line syntax error',CR,LF,CR,LF,0
  801.     JMP    HELP        ;GIVE HELP MSG TOO
  802. ;
  803. AFNERR:    CALL    ERRXIT        ;EXIT WITH MESSAGE
  804.     DB    'Ambiguous file name: % not allowed.',0
  805. ;
  806. FNFERR:    CALL    ERRXIT
  807.     DB    'File % not found.',0
  808. ;
  809. DSKFUL:    CALL    ERRXIT
  810.     DB    'Disk full.',0
  811. ;
  812. DIRFUL:    CALL    ERRXIT
  813.     DB    'Directory full.',0
  814. ;
  815. EOFERR:    CALL    ERRXIT
  816.     DB    'Premature end-of-file in %',0
  817. ;
  818. CSERR:    CALL    ERRXIT
  819.     DB    'Checksum error in %',0
  820. ;
  821. CLSERR:    CALL    ERRXIT
  822.     DB    'Can''t close %',0
  823. ;
  824. MEMFUL:    CALL    ERRXIT
  825.     DB    'Memory full while loading %',0
  826. ;
  827. FORMERR:CALL    ERRXIT
  828.     DB    'Format error in file %',0
  829. ;
  830. LODERR:    CALL    ERRXIT
  831.     DB    'Writing %, nothing loaded',0
  832. ;
  833. HELP:    CALL    ERRXIT        ;PRINT HELP TEXT
  834.     DB    'MLOAD syntax:',CR,LF,CR,LF
  835.     DB    '    MLOAD [<OUTFIL>=] <FILE1>[,<FILE2>...] [<BIAS>]',CR,LF
  836.     DB    '       (brackets denote optional items)',CR,LF
  837.     DB    '    <OUTFIL> is the optional output filename',CR,LF
  838.     DB    '    <FILEn> are input file(s)',CR,LF
  839.     DB    '    <BIAS> is a load offset (in hex) within the output file'
  840.     DB    CR,LF,0
  841. ;
  842. ; GENERAL ERROR HANDLER
  843. ;
  844. ERRXIT:    CALL    CRLF        ;NEW LINE
  845.     POP    H        ;FETCH ERROR MSG POINTER
  846.     CALL    PRATHL        ;PRINT IT
  847.     CALL    CRLF
  848.     JMP    EXIT        ;DONE
  849. ;
  850. ;    *********************************
  851. ;    * FILE NAME PARSING SUBROUTINES *
  852. ;    *********************************
  853. ;
  854. ; CREDIT WHERE CREDIT'S DUE:
  855. ; --------------------------
  856. ; THESE ROUTINES WERE LIFTED FROM BOB VAN VALZAH'S
  857. ; "FAST" PROGRAM.
  858. ;
  859. ;
  860. ; GETFN GETS A FILE NAME FROM TEXT POINTED TO BY REG HL INTO
  861. ; AN FCB POINTED TO BY REG DE.    LEADING DELIMETERS ARE 
  862. ; IGNORED.
  863. ; ENTRY DE    FIRST BYTE OF FCB
  864. ; EXIT B=# OF '?' IN NAME
  865. ;
  866. ;
  867. FPARSE:    CALL    NITFCB        ;INIT 1ST HALF OF FCB
  868.     MVI    B,0        ;INIT AMBIG REF COUNTER
  869.     CALL    GSTART        ;SCAN TO FIRST CHARACTER OF NAME
  870.     RZ            ;END OF LINE WAS FOUND - LEAVE FCB BLANK
  871.     CALL    GETDRV        ;GET DRIVE SPEC. IF PRESENT
  872.     CALL    GETPS        ;GET PRIMARY AND SECONDARY NAME
  873.     RET
  874. ;
  875. ; NITFCB FILLS THE FCB WITH DFLT INFO - 0 IN DRIVE FIELD
  876. ; ALL-BLANK IN NAME FIELD, AND 0 IN EX,S1,S2,RC, DISK
  877. ; ALLOCATION MAP, AND RANDOM RECORD # FIELDS
  878. ;
  879. NITFCB:    PUSH    D        ;SAVE FCB LOC
  880.     XCHG            ;MOVE IT TO HL
  881.     MVI    M,0        ;ZAP DR FIELD
  882.     INX    H        ;BUMP TO NAME FIELD
  883.     MVI    B,11        ;ZAP ALL OF NAME FLD
  884. FNITLP: MVI    M,' '
  885.     INX    H
  886.     DCR    B
  887.     JNZ    FNITLP
  888.     MVI    B,FCBSIZ-12    ;ZERO OTHERS, UP TO NR FIELD
  889. FNIT2:    MVI    M,0
  890.     INX    H
  891.     DCR    B
  892.     JNZ    FNIT2
  893.     XCHG            ;RESTORE HL
  894.     POP    D        ;RESTORE FCB POINTER
  895.     RET
  896. ;
  897. ; GSTART ADVANCES THE TEXT POINTER (REG HL) TO THE FIRST
  898. ; NON DELIMITER CHARACTER (I.E. IGNORES BLANKS).  RETURNS A
  899. ; FLAG IF END OF LINE (00H OR ';') IS FOUND WHILE SCANING.
  900. ; EXIT    HL    POINTING TO FIRST NON DELIMITER
  901. ;    A    CLOBBERED
  902. ;    ZERO    SET IF END OF LINE WAS FOUND
  903. ;
  904. GSTART: CALL    GETCH        ;SEE IF POINTING TO DELIM?
  905.     RNZ            ;NOPE - RETURN
  906.     ORA    A
  907.     RZ            ;YUP - RETURN W/FLAG
  908.     INX    H        ;NOPE - MOVE OVER IT
  909.     JMP    GSTART         ;AND TRY NEXT CHAR
  910. ;
  911. ; GETDRV CHECKS FOR THE PRESENCE OF A DRIVE SPEC AT THE TEXT
  912. ; POINTER, AND IF PRESENT FORMATS IT INTO THE FCB AND
  913. ; ADVANCES THE TEXT POINTER OVER IT.
  914. ; ENTRY HL    TEXT POINTER
  915. ;    DE    POINTER TO FIRST BYTE OF FCB
  916. ; EXIT    HL    POSSIBLY UPDATED TEXT POINTER
  917. ;    DE    POINTER TO SECOND (PRIMARY NAME) BYTE OF FCB
  918. ;
  919. GETDRV: INX    D        ;POINT TO NAME IF SPEC NOT FOUND
  920.     INX    H        ;LOOK AHEAD TO SEE IF ':' PRESENT
  921.     MOV    A,M
  922.     DCX    H        ;PUT BACK IN CASE NOT PRESENT
  923.     CPI    ':'        ;IS A DRIVE SPEC PRESENT?
  924.     RNZ            ;NOPE - RETURN
  925.     MOV    A,M        ;YUP - GET THE ASCII DRIVE NAME
  926.     SUI    'A'-1        ;CONVERT TO FCB DRIVE SPEC
  927.     DCX    D        ;POINT BACK TO DRIVE SPEC BYTE
  928.     STAX    D        ;STORE SPEC INTO FCB
  929.     INX    D        ;POINT BACK TO NAME
  930.     INX    H        ;SKIP OVER DRIVE NAME
  931.     INX    H        ;AND OVER ':'
  932.     RET
  933. ;
  934. ; GETPS GETS THE PRIMARY AND SECONDARY NAMES INTO THE FCB.
  935. ; ENTRY HL    TEXT POINTER
  936. ; EXIT    HL    CHARACTER FOLLOWING SECONDARY NAME (IF PRESENT)
  937. ;
  938. GETPS:    MVI    C,8        ;MAX LENGTH OF PRIMARY NAME
  939.     CALL    GETNAM        ;PACK PRIMARY NAME INTO FCB
  940.     MOV    A,M        ;SEE IF TERMINATED BY A PERIOD
  941.     CPI    '.'
  942.     RNZ            ;NOPE - SECONDARY NAME NOT GIVEN
  943.                 ;RETURN DEFAULT (BLANKS)
  944.     INX    H        ;YUP - MOVE TEXT POINTER OVER PERIOD
  945. FTPOINT:MOV    A,C        ;YUP - UPDATE FCB POINTER TO SECONDARY
  946.     ORA    A
  947.     JZ    GETFT
  948.     INX    D
  949.     DCR    C
  950.     JMP    FTPOINT
  951. GETFT:    MVI    C,3        ;MAX LENGTH OF SECONDARY NAME
  952.     CALL    GETNAM        ;PACK SECONDARY NAME INTO FCB
  953.     RET
  954. ;
  955. ; GETNAM COPIES A NAME FROM THE TEXT POINTER INTO THE FCB FOR
  956. ; A GIVEN MAXIMUM LENGTH OR UNTIL A DELIMITER IS FOUND, WHICH
  957. ; EVER OCCURS FIRST.  IF MORE THAN THE MAXIMUM NUMBER OF
  958. ; CHARACTERS IS PRESENT, CHARACTER ARE IGNORED UNTIL A
  959. ; A DELIMITER IS FOUND.
  960. ; ENTRY HL    FIRST CHARACTER OF NAME TO BE SCANNED
  961. ;    DE    POINTER INTO FCB NAME FIELD
  962. ;    C    MAXIMUM LENGTH
  963. ; EXIT    HL    POINTING TO TERMINATING DELIMITER
  964. ;    DE    NEXT EMPTY BYTE IN FCB NAME FIELD
  965. ;    C    MAX LENGTH - NUMBER OF CHARACTERS TRANSFERED
  966. ;
  967. GETNAM: CALL    GETCH        ;ARE WE POINTING TO A DELIMITER YET?
  968.     RZ            ;IF SO, NAME IS TRANSFERED
  969.     INX    H        ;IF NOT, MOVE OVER CHARACTER
  970.     CPI    '*'        ;AMBIGIOUS FILE REFERENCE?
  971.     JZ    AMBIG        ;IF SO, FILL THE REST OF FIELD WITH '?'
  972.     CPI    '?'        ;AFN REFERENCE?
  973.     JNZ    NOTQ        ;SKIP IF NOT
  974.     INR    B        ;ELSE BUMP AFN COUNT
  975. NOTQ:    STAX    D        ;AND COPY INTO NAME FIELD
  976.     INX    D        ;INCREMENT NAME FIELD POINTER
  977.     DCR    C        ;IF NAME FIELD FULL?
  978.     JNZ    GETNAM        ;NOPE - KEEP FILLING
  979.     JMP    GETDEL        ;YUP - IGNORE UNTIL DELIMITER
  980. AMBIG:    MVI    A,'?'        ;FILL CHARACTER FOR WILD CARD MATCH
  981. FILLQ:    STAX    D        ;FILL UNTIL FIELD IS FULL
  982.     INX    D
  983.     INR    B        ;INCREMENT COUNT OF '?'
  984.     DCR    C
  985.     JNZ    FILLQ        ;FALL THRU TO INGORE REST OF NAME
  986. GETDEL: CALL    GETCH        ;POINTING TO A DELIMITER?
  987.     RZ            ;YUP - ALL DONE
  988.     INX    H        ;NOPE - IGNORE ANTOHER ONE
  989.     JMP    GETDEL
  990. ;
  991. ; GETCH GETS THE CHARACTER POINTED TO BY THE TEXT POINTER
  992. ; AND SETS THE ZERO FLAG IF IT IS A DELIMITER.
  993. ; ENTRY HL    TEXT POINTER
  994. ; EXIT    HL    PRESERVED
  995. ;    A    CHARACTER AT TEXT POINTER
  996. ;    Z    SET IF A DELIMITER
  997. ;
  998. GETCH:    MOV    A,M        ;GET THE CHARACTER
  999.     CPI    '/'
  1000.     RZ
  1001.     CPI    '.'
  1002.     RZ
  1003.     CPI    ','
  1004.     RZ      
  1005.     CPI    ' '
  1006.     RZ
  1007.     CPI    ':'
  1008.     RZ
  1009.     CPI    '='
  1010.     RZ
  1011.     ORA    A        ;SET ZERO FLAG ON END OF TEXT
  1012.     RET
  1013. ;
  1014. ; VARIABLES
  1015. ;
  1016. SPSAVE:    DS    2        ;SYSTEM STACK PNTR SAVE
  1017. BIAS:    DS    2        ;LOAD OFFSET
  1018. HILOAD:    DS    2        ;HIGHEST TRUE LOAD ADDRESS
  1019. HIPC:    DS    2        ;HIGHEST PC
  1020. CKSUM:    DS    1        ;RECORD CHECKSUM
  1021. CMDPTR:    DS    2        ;COMMAND LINE POINTER
  1022. BUFPTR:    DS    1        ;INPUT BUFFER POINTER
  1023. LODFLG:    DS    1        ;SOMETHING-LOADED FLAG
  1024. FILBUF:    DS    2        ;FILE BUFFER LOCATION
  1025. OFFSET:    DS    2        ;LOAD OFFSET INTO BUFFER
  1026. LODADR:    DS    2        ;LOAD ADDRESS
  1027. OUTNAM:    DS    12        ;OUTPUT DRIVE+NAME
  1028. RECCNT:    DS    2        ;OUTPUT FILE RECORD COUNT
  1029. BYTCNT:    DS    2        ;OUTPUT FILE BYTES LOADED  COUNT
  1030. ;
  1031.     DS    80        ;40-LEVEL STACK
  1032. ;
  1033. STACK    EQU    $
  1034. CMDBUF    EQU    $        ;COMMAND BUFFER LOCATION
  1035. ;
  1036. ;
  1037.     END
  1038.