;************************************************************************ ;* * ;* UNLOAD23: This is an enhancement of the old unload 2.1 * ;* It has the ability to output 8 byte,16 byte, 32 byte, or * ;* 64 byte Intel hex records. It also no-longer requires the * ;* input file to be .COM, it can be anything. Also fixed the * ;* EOF record output, the previous style of EOF record has been * ;* known to cause some equipment/software to "choke". * ;* * ;* --->Needs MAC and SEQIO.LIB to assemble<--- * ;* * ;************************************************************************ ;* * ;* Revision history: * ;* * ;*01/18/88 Added HELP message if command line is invalid or missing. * ;* By Tom A. Head. * ;* * ;*09/05/87 Major revision. Added run-time switch for record size, * ;* allowed file types other than .COM to be used, and added * ;* code to output a true EOF record instead of the "fake" * ;* MAC style previously output by the program. Also added * ;* COMMENTS, the program was poorly commented. * ;* By Mark D. Pickerill, on IMSAI-8080. * ;* * ;*05/20/81 Modified for 32 bytes/record instead of 16, for less * ;* overhead in the .HEX output file, by Dav Holle. * ;* * ;*11/07/80 Modified to default to 100H, increase size of buffers, * ;* add signon message. By Keith Petersen, W8SDZ * ;* * ;*Originally from CPMUG 29.23 * ;* * ;*To use, type: UNLOAD <.EXT> * ;* * ;*Where: is the source file, <.EXT> if not given defaults * ;* to .COM * ;* .HEX will be the output file * ;* is the optional start address in hex (default=100) * ;* is the optional record size, where /X is: * ;* * ;* /S Small, 08 bytes per record * ;* /M Medium, 16 bytes per record (default) * ;* /L Large, 32 bytes per record * ;* /E Extra, 64 bytes per record * ;* Note that this format is known to make PIP's [H] "choke" * ;* * ;************************************************************************ ; FCB2 EQU 006CH ; Location of second fcb FCB1EXT:EQU 0065H ; Location of ext field of first fcb ORG 100H ; Start of tpa MACLIB SEQIO ; Define macro library used LHLD 6 ; Get base of bdos DCX H ; Back off one byte SPHL ; Set stack there CALL SIGNON ; Jump around message w/msg addr on stack DB CR,LF,'UNLOAD ver 2.3',CR,LF,'$' DB '01/18/88' ; Revision date (doesn't print) ; HELP: LXI D,USAGE ; Point to help message MVI C,@MSG ; Print message function CALL @BDOS ; Print message JMP 0 ; And exit ; USAGE: DB CR,LF ; DB 'UNLOAD.COM creates a .HEX file from a .COM file.',CR,LF DB CR,LF,' Usage: UNLOAD [d:]FILENAME[.TYP] [ADDR][/x]' DB CR,LF,CR,LF ; DB 'd: is the optional source drive.',CR,LF DB 'FILENAME is the source file.',CR,LF DB '.TYP is the optional filetype and if not',CR,LF DB 'specified will default to .COM',CR,LF DB 'ADDR is an optional HEX start address (default = 0100)' DB CR,LF ; DB '/x is an optional record size where x may be S,M,L or E' DB CR,LF ; DB 'to denote a record size of 8,16,32 or 64 bytes.',CR,LF DB 'The default size is M (16 bytes).' DB CR,LF ; DB 'FILENAME.HEX will be the output file',CR,LF,CR,LF DB 'Example: UNLOAD C:FOOBAR.OBJ F800/L' DB CR,LF,'$' ; ; SIGNON: POP D ; Get msg adr MVI C,@MSG ; Print it CALL @BDOS ; Do it ; LDA @TBUF ; Get command line character count CPI 4 ; Too short to be valid? JC HELP ; Yes, give help ; MVI A,16 ; Default record size STA SIZE ; Store it LDA FCB1EXT ; Point to file ext field of fcb1 CPI ' ' ; Ext specified? CZ PUTCOM ; No ext, force default to .com LXI H,0100H ; Default unload adrs LXI D,FCB2+1 ; Look at first location of second fcb LDAX D ; Get option adrs CPI '/' ; Check first for no address, opt. rec size CZ SETSIZE ; Yes, change size CPI ' ' ; Any given? JZ INITFL ; No, default to 0100h LXI H,0 ; Zero 16 bit accumulator MVI B,0 ; Zero b (unused) ; ADRLUP: LDAX D ; Get char CPI '/' ; Change size switch? CZ SETSIZE ; Yes INX D ; Point to next SUI '0' ; Remove numeric bias JC INITFL ; CPI 10 ; Punctuation? JC ADDNIB ; No SUI 7 ; Yes, remove punctuation bias JC INITFL ; Not valid hex, actually was punctuation CPI 16 ; Higher than f? JNC INITFL ; Yes, invalid ; ADDNIB: DAD H ; Multiply 16 bit accumulator by 2 DAD H ; 4 DAD H ; 8 DAD H ; 16 MOV C,A ; Move current value DAD B ; Add in current value to 16 bit acc JMP ADRLUP ; And do until garbage is found ; SETSIZE:INX D ; Point to next LDAX D ; Get it CPI 'S' ; Small (08)? MVI B,08D ; In-case it is... JZ SETIT ; Yes CPI 'M' ; Medium (16)? MVI B,16D ; In-case it is... JZ SETIT ; Yes CPI 'L' ; Large (32)? MVI B,32D ; In-case it is... JZ SETIT ; Yes CPI 'E' ; Extra (64)? MVI B,64D ; In-case it is... JZ SETIT ; Yes MVI B,16D ; Garbage, retain default SETIT: MOV A,B ; Get desired setting STA SIZE ; Set mem location MVI A,' ' ; To force termination of option search routine RET ; Go home ; PUTCOM: MVI B,3 ; Three bytes in .com LXI H,FCB1EXT ; Point to fcb1 ext field LXI D,COM ; Point to the word 'com' PUTLP: LDAX D ; Get byte MOV M,A ; Put byte DCR B ; Count down INX H ; Increment destination INX D ; Increment source JNZ PUTLP ; Loop til done RET ; Go home ; COM: DB 'COM' ; Com files are default ; INITFL: PUSH H ; Save load address FILE INFILE,SOURCE,,1,,2048 ; Invoke macro FILE OUTFILE,OUTPUT,,1,HEX,2048 ; Invoke macro POP H ; Restore load address ; ADRDON: SHLD LODADR ; Save unload address UNLOOP: GET SOURCE ; Get byte of source JZ GEOF ; Done, generate eof record PUSH PSW ; Save it MVI A,':' ; Get a colon PUT OUTPUT ; Write it to the output XRA A ; Zero acc STA CHEKS ; And store in checksum byte LDA SIZE ; Get record size CALL PUTBYTE ; Output the record lenth LDA LODADR+1 ; Get msb of load address CALL PUTBYTE ; Output it LDA LODADR ; Now the lsb CALL PUTBYTE ; Output it XRA A ; Record type 00 CALL PUTBYTE ; Dump it LDA SIZE ; Get record size MOV B,A ; And put in b POP PSW ; Recover current byte LINLUP: PUSH B ; Save line count CALL PUTBYTE ; Output current byte POP B ; Recover line count DCR B ; Decrement it JZ NEXTL ; If done, process end of line GET SOURCE ; If not, get next byte JMP LINLUP ; And loop until a whole line is done ; NEXTL: LDA CHEKS ; Get checksum CALL PUTBYTE ; Output it MVI A,CR ; A carriage return PUT OUTPUT ; Dump it MVI A,LF ; A line feed PUT OUTPUT ; Dump it LHLD LODADR ; Get load address LDA SIZE ; Get record size MOV E,A ; Into e MVI D,00 ; Zero msb of de DAD D ; Add in line length for next record JMP ADRDON ; Do til done with file ; PUTBYTE:MOV C,A ; Save byte in c LDA CHEKS ; Get current checksum SUB C ; Subtract current byte (auto 2's comp.) STA CHEKS ; Put back MOV A,C ; Restore current byte RRC ; Get msn RRC ; Takes RRC ; Four RRC ; Rotates CALL PUTNIB ; Stuff nybble MOV A,C ; Get lsn back, and drop into putnib ; PUTNIB: ANI 0FH ; Strip upper nybble ADI '0' ; Add numeric bias CPI '9'+1 ; 9 or less? JC PUTNB1 ; Yes ADI 7 ; No, add in alpha bias PUTNB1: PUSH B ; Save b PUT OUTPUT ; Write the ascii byte POP B ; Restore b RET ; Go home ; GEOF: MVI A,':' ; A colon PUT OUTPUT ; Output it MVI B,3 ; 5 bytes GEOF1: XRA A ; Generate a zero PUSH B ; Save count CALL PUTBYTE ; Output the zero POP B ; Recover count DCR B ; Decrement JNZ GEOF1 ; Do till done MVI A,01H ; Record type 01, eof CALL PUTBYTE ; Output it MVI A,0FFH ; Checksum for eof record CALL PUTBYTE ; Output it MVI A,CR ; Output the cr PUT OUTPUT ; Do it MVI A,LF ; Output the lf PUT OUTPUT ; Do that too FINIS OUTPUT ; Close output file LXI D,DMSG ; Tell world we're done MVI C,@MSG ; Function # CALL @BDOS ; Do it JMP 0 ; Good bye ; DMSG: DB 'Done',CR,LF,'$' ; Message ; SIZE: DS 1 ; Record size storage LODADR: DS 2 ; Load address storage CHEKS: DS 1 ; Checksum storage BUFFERS EQU $ ; Input/output buffers go here ; END ;