home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / beehive / program / unload.arc / UNLOAD.MAC < prev   
Encoding:
Text File  |  1990-07-22  |  9.9 KB  |  416 lines

  1. ;UNLOAD.MAC - A program to turn COM files into HEX.
  2. ;    Disassembled and commented by Ted Harper
  3. ;
  4.     .Z80
  5. ;
  6. BDOS        EQU     0005
  7. InFCB        EQU    005Ch
  8. InputFileName     EQU     005Dh
  9. InFCBExt    EQU    0065h    ;Location of .EXT part of name of input file
  10. InFCBExtent    EQU    0068h    ;Location where current file extent is stored
  11. InFCBRecCount    EQU    006Ah    ;Location where current record count is held
  12. InFCBD0        EQU    006Dh    ;Location of D0 byte in input FCB
  13. InFCBCurrRecNum    EQU    007Ch    ;Current record number
  14. TPAStart    equ    0100h
  15. ;
  16. CR        equ    0Dh    ;ASCII character equates
  17. LF        equ    0Ah
  18. ;
  19. ;    BDOS functions
  20. ;
  21. BDOSPrintString    equ    09
  22. BDOSOpenFile    equ    0Fh
  23. BDOSCloseFile    equ    10h
  24. BDOSDeleteFile    equ    13h
  25. BDOSReadSector    equ    14h
  26. BDOSWriteSector    equ    15h
  27. BDOSMakeFile    equ    16h
  28. BDOSSetDMA    equ    1Ah
  29. ;
  30.     aseg
  31.     org    0100h
  32. ;
  33.     CALL    Start
  34.     DB    'UNLOAD Version 2.03'
  35.     DB    0Dh,0Ah
  36.     DB    '$'
  37. ;
  38. Start:
  39.     POP    DE            ;Restore pointer to message
  40.     LD    (StackPtrSave),SP    ;Save entry stack pointer
  41.     LD    SP,LocalStackTop    ;Set up local stack
  42. ;
  43.     LD    C,BDOSPrintString    ;Print signon message above
  44.     CALL    BDOS
  45. ;
  46.     CALL    CheckInputFiletype    ;Check the filetype for the input
  47.                     ;file and return start address
  48. ;
  49.     PUSH    HL        ;Save start address of output file
  50. ;
  51.     LD    HL,InFCB    ;Move "FILENAME" part of filename to output
  52.     LD    DE,OutFCB    ;FCB
  53.     LD    BC,0009        ;9 bytes to move
  54.     LDIR
  55. ;Move "HEX" to "ext" part of filename in output FCB
  56.     LD    HL,OutFileType    ;Move "HEX" to ".EXT" part of filename in
  57.     LD    DE,OutFCBExt    ;output FCB
  58.     LD    BC,0003        ;3 bytes to move
  59.     LDIR
  60. ;
  61.     CALL    OpenInputFile    ;Open both the input and output files
  62.     CALL    OpenOutputFile
  63. ;
  64.     LD    B,08        ;Output the "filename" part of the filename
  65.     LD    HL,InputFileName    ;to the hex file (8 characters)
  66. OutputFNLoop:
  67.     LD    A,(HL)
  68.     CALL    OutputCharToHEXFile
  69.     INC    HL
  70.     DJNZ    OutputFNLoop
  71. ;
  72.     CALL    OutputCRLFtoHEXFile    ;Output CR and LF to HEX file
  73. ;
  74.     POP    HL        ;Restore start address of output file
  75. ;
  76. Unload32Bytes:
  77. ;This code writes one "line" of the HEX file out. It
  78. ;usually consists of a colon, then the address of
  79. ;the start of the line, then 32 hex numbers, then
  80. ;a checksum. It ends with a CR+LF pair
  81. ;
  82.     LD    B,32        ;Set loop index to 32 bytes to process
  83. ;
  84.     LD    A,':'        ;Start each line with a ':'
  85.     CALL    OutputCharToHEXFile
  86. ;
  87.     CALL    GetAByteFromInput    ;Read a byte in from the COM file
  88.     JR    C,InputEOFReached    ;Carry is set if last byte done
  89.     PUSH    AF
  90.     LD    C,00        ;Initialise checksum to 00
  91. ;
  92.     LD    A,B        ;Output 20h (number of bytes this line)
  93.     CALL    Output2HexNibbles
  94. ;
  95.     LD    A,H        ;Output start address for this line
  96.     CALL    Output2HexNibbles
  97.     LD    A,L
  98.     CALL    Output2HexNibbles
  99. ;
  100.     XOR    A        ;Output a zero after the address
  101.     CALL    Output2HexNibbles
  102. ;
  103.     POP    AF        ;Restore the first byte read
  104.     JR    Proc32ByteEntry    ;Enter the processing loop
  105.  
  106. ;The following loop outputs the next 32 bytes from
  107. ;the input file as hex numbers in ascii format.
  108. ;
  109. Proc32ByteLoop:
  110.     CALL    GetAByteFromInput    ;Read a byte from the input file
  111. ;
  112. Proc32ByteEntry:
  113.     CALL    Output2HexNibbles    ;Output the byte in A in hex.
  114.     INC    HL            ;Bump index to next byte
  115.     DJNZ    Proc32ByteLoop        ;Loop to process 32 bytes
  116. ;
  117. ;Now the checksum must be output. It was maintained
  118. ;in the C-reg during the above processing loop.
  119. ;
  120.     LD    A,C        ;Put the checksum into the acc.
  121.     NEG            ;Invert all bits??
  122.     CALL    Output2HexNibbles    ;Output it to the HEX file
  123. ;
  124.     CALL    OutputCRLFtoHEXFile    ;Finish each line with CR+LF pair
  125. ;
  126.     JR    Unload32Bytes    ;Loop back to process another 32 bytes
  127. ;
  128. InputEOFReached:
  129. ;Finish off by writing 5 zero bytes to the hex file
  130. ;
  131.     LD    B,5        ;Finish off by writing 5 '0' bytes to hex file
  132. OutputZerosLoop:
  133.     XOR    A
  134.     CALL    Output2HexNibbles
  135.     DJNZ    OutputZerosLoop
  136. ;
  137.     CALL    OutputCRLFtoHEXFile    ;Finish off with CR+LF
  138. ;
  139.     CALL    CloseOutputFile        ;Write some ^Z's to output & close up
  140. ;
  141.     LD    SP,(StackPtrSave) ;Restore stack pointer and return to CP/M
  142. ;
  143.     RET
  144. ;
  145. PrintAndExit:
  146.     LD    C,BDOSPrintString    ;Print a message (DE points to it)
  147.     CALL    BDOS
  148.     JP    0000        ;and warm boot to CP/M
  149. ;
  150. OutputCRLFtoHEXFile:
  151.     LD    A,CR        ;Write a CR and an LF to the hex file
  152.     CALL    OutputCharToHEXFile
  153.     LD    A,LF
  154.     JP    OutputCharToHEXFile
  155. ;
  156. Output2HexNibbles:
  157. ;Output the character in A as two ASCII hex nibbles
  158.     PUSH    AF
  159.     ADD    A,C
  160.     LD    C,A
  161.     POP    AF
  162.     PUSH    AF
  163.     RRCA
  164.     RRCA
  165.     RRCA
  166.     RRCA
  167.     CALL    OutputANibble
  168.     POP    AF
  169. OutputANibble:
  170.     AND    0Fh
  171.     ADD    A,90h
  172.     DAA
  173.     ADC    A,'@'
  174.     DAA
  175.     JP    OutputCharToHEXFile
  176. ;
  177. AddAtoHL:
  178. ;Adds the value in A to that in HL
  179.     ADD    A,L
  180.     LD    L,A
  181.     RET    NC
  182.     INC    H
  183.     RET
  184. ;
  185. CheckInputFiletype:
  186.     LD    DE,InFCBD0
  187.     LD    HL,0000
  188. ;
  189.     LD    A,(InFCBExt)    ;Check the first byte of input filename ".EXT"
  190.     AND    7Fh        ;Mask the attribute bit off
  191.     CP    'C'        ;Is it a 'C'
  192.     JR    NZ,NotCOM    ;If not, things get more difficult
  193. ;
  194.     LD    A,(InFCBExt+1)    ;Check if second byte is 'O' in same manner
  195.     AND    7Fh
  196.     CP    'O'
  197.     JR    NZ,NotCOM
  198. ;
  199.     LD    A,(InFCBExt+2)    ;Check if third byte is 'M' in same manner
  200.     AND    7Fh
  201.     CP    'M'
  202.     JR    NZ,NotCOM
  203. ;
  204.     LD    HL,TPAStart    ;It is a COM file so return HL = 100h
  205. ;
  206. NotCOM:
  207. ;The filetype is not COM, work a bit harder to get load address
  208.     LD    A,(DE)
  209.     CP    ' '
  210.     RET    Z
  211.     LD    HL,0000
  212. GrungeLoop1:
  213.     LD    A,(DE)
  214.     INC    DE
  215.     SUB    '0'
  216.     RET    C
  217.     CP    0Ah
  218.     JR    C,LessThan10
  219.     SUB    07
  220.     CP    0Ah
  221.     RET    C
  222.     CP    10h
  223.     RET    NC
  224. LessThan10:
  225.     ADD    HL,HL
  226.     ADD    HL,HL
  227.     ADD    HL,HL
  228.     ADD    HL,HL
  229.     ADD    A,L
  230.     LD    L,A
  231.     JR    GrungeLoop1
  232. ;
  233. OpenInputFile:
  234.     LD    HL,0000
  235.     LD    (InFCBExtent),HL    ;Zero "current extent number"
  236.     LD    (InFCBRecCount),HL    ;zero record count for extent
  237.     XOR    A        ;Set "Current record to read" to zero
  238.     LD    (InFCBCurrRecNum),A
  239. ;
  240. ;Initialise counter to force sector read when first
  241. ;byte requested by main processing loop
  242. ;
  243.     LD    A,80h
  244.     LD    (BytesReadFromBuffer),A
  245. ;
  246.     LD    DE,InFCB    ;Open the input file
  247.     LD    C,BDOSOpenFile
  248.     CALL    BDOS
  249. ;
  250. ;Return if file opened OK, otherwise exit with error msg
  251.     LD    DE,FileNotExistMsg    ;Return if file opened OK, otherwise
  252.     INC    A        ;exit with error message
  253.     JP    Z,PrintAndExit
  254.     RET
  255. ;
  256. GetAByteFromInput:
  257.     PUSH    HL        ;Save the current "work" pointer
  258. ;
  259.     LD    HL,InputDMABuffer
  260.     LD    A,(BytesReadFromBuffer)    ;Find how many bytes we've used up
  261.     INC    A
  262. ;Result is +ve if < 128 (i.e. not all bytes used yet)
  263.     JP    P,InBufferNotExhausted
  264. ;
  265.     PUSH    BC        ;No bytes left in buffer, read another sector
  266.     PUSH    DE
  267.     PUSH    HL
  268. ;
  269.     EX    DE,HL        ;Set DMA address to input file buffer
  270.     LD    C,BDOSSetDMA
  271.     CALL    BDOS
  272. ;Read a sector from the input file into the DMA area
  273.     LD    DE,InFCB    ;Read a sector from the input file into the
  274.     LD    C,BDOSReadSector    ;DMA area
  275.     CALL    BDOS
  276. ;
  277.     POP    HL
  278.     POP    DE
  279.     POP    BC
  280.     AND    A
  281.     LD    A,1Ah        ;Put a CTRL-Z into acc (just in case)
  282. ;
  283.     SCF            ;Set Carry flag and exit if EOF reached
  284.     JR    NZ,EOFInputReached
  285. ;
  286.     XOR    A        ;EOF not reached, zero "bytes used" counter
  287. ;
  288. InBufferNotExhausted:
  289.     LD    (BytesReadFromBuffer),A    ;Save number of bytes read from buffer
  290.     CALL    AddAtoHL    ;Set HL to point to the right byte to get
  291.     LD    A,(HL)        ;Get a byte out of the buffer
  292.     AND    A        ;Set whatever flags
  293. ;
  294. EOFInputReached:
  295.     POP    HL        ;Common exit point for this routine
  296.     RET
  297. ;
  298. OpenOutputFile:
  299.     LD    HL,0000
  300.     LD    (OutFCBExtent),HL    ;Zero "current extent" field in FCB
  301.     LD    (OutFCBRecCount),HL    ;zero record count for extent
  302.     XOR    A        ;Set "current record to write" to zero
  303.     LD    (OutFCBCurrRecNum),A
  304. ;
  305.     LD    (BytesHeldForOutput),A    ;zero counter of "held" bytes
  306. ;
  307.     LD    DE,OutFCB    ;Set DE to point to output FCB
  308.     PUSH    DE
  309. ;
  310.     LD    C,BDOSDeleteFile    ;Delete the file if it exists
  311.     CALL    BDOS
  312. ;
  313.     POP    DE        ;Make the file (like "rewrite" in Pascal)
  314.     LD    C,BDOSMakeFile
  315.     CALL    BDOS
  316. ;if BDOS returned FF, then couldn't find directory space
  317.     LD    DE,DirectoryFullMsg    ;If BDOS returned 0FFh, then couldn't
  318.     INC    A        ;make file, so exit
  319.     JP    Z,PrintAndExit    ;otherwise just return
  320.     RET
  321.  
  322. OutputCharToHEXFile:
  323. ;Output a character to the HEX file being created.
  324. ;Actually, the routine holds 128 characters, then
  325. ;writes a whole sector when it needs to.
  326.     PUSH    HL
  327.     PUSH    AF
  328. ;Get address to store the byte in by adding the start
  329. ;address of the buffer to the number of bytes already
  330. ;held there.
  331.     LD    HL,OutputBuffer
  332.     LD    A,(BytesHeldForOutput)
  333.     CALL    AddAtoHL
  334.     POP    AF
  335. ;Save the byte in the output buffer
  336.     LD    (HL),A
  337. ;Add 1 to the tally of bytes held awaiting output
  338.     LD    A,(BytesHeldForOutput)
  339.     INC    A
  340. ;If a is +ve, then < 128 bytes are held, so sector is
  341. ;not full & doesn't need to be written
  342.     JP    P,OutputSectorNotFull
  343. ;Output buffer is full...write buffer to disk
  344.     PUSH    BC
  345.     PUSH    DE
  346. ;Set DMA address to output DMA area
  347.     LD    DE,OutputBuffer
  348.     LD    C,BDOSSetDMA
  349.     CALL    BDOS
  350. ;Write a sector to the output file
  351.     LD    DE,OutFCB
  352.     LD    C,BDOSWriteSector
  353.     CALL    BDOS
  354. ;Cancel program if error returned, otherwise continue
  355.     LD    DE,DiskFullMsg
  356.     AND    A
  357.     JP    NZ,PrintAndExit
  358. ;no write error, life can continue
  359. ;A contains zero here (conveniently), so doesn't need
  360. ;to be zeroed before saving as "held" count
  361.     POP    DE
  362.     POP    BC
  363. ;
  364. OutputSectorNotFull:
  365. ;Save the number of bytes held in the buffer
  366.     LD    (BytesHeldForOutput),A
  367.     POP    HL
  368.     RET
  369. ;
  370. CloseOutputFile:
  371. ;Output a number of ctrl-Z characters to the output
  372. ;file until the current sector has been filled.
  373. OutputCtrlZLoop:
  374.     LD    A,1Ah    ;^Z character (used as eof padding)
  375.     CALL    OutputCharToHEXFile
  376.     AND    A
  377.     JR    NZ,OutputCtrlZLoop
  378. ;Close the output file
  379.     LD    DE,OutFCB
  380.     LD    C,BDOSCloseFile
  381.     CALL    BDOS
  382. ;If 0FFh returned, close failed, so abort with error msg
  383.     LD    DE,FileNotExistMsg
  384.     INC    A
  385.     JP    Z,PrintAndExit
  386.     RET
  387.  
  388. DirectoryFullMsg:
  389.     DB    'Directory Full$'
  390. DiskFullMsg:
  391.     DB    'Disk Full$'
  392. FileNotExistMsg:
  393.     DB    'File does not exist$'
  394. OutFileType:
  395.     DB    'HEX'
  396. BytesReadFromBuffer:
  397.     DB    0
  398. InputDMABuffer:
  399.    DB   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  400.    DB   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  401.    DB   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  402.    DB   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  403. ;
  404. OutFCB        EQU    0388h
  405. OutFCBExt    EQU    0391h
  406. OutFCBExtent    EQU    0394h
  407. OutFCBRecCount    EQU    0396h
  408. OutFCBCurrRecNum EQU    03A8h
  409. BytesHeldForOutput EQU    03A9h
  410. OutputBuffer    EQU    03AAh
  411. StackPtrSave    EQU    042Ah
  412. LocalStackTop    EQU    046Ch
  413. ;
  414.         END
  415. um EQU    03A8h
  416. BytesHeldForOutput EQU    03A