home *** CD-ROM | disk | FTP | other *** search
- ;************************************************************************
- ;* *
- ;* UNLOAD86.A86 This is a MS-DOS unload program. See the help *
- ;* screen at the end of this file for details on its use. *
- ;* Written by: Mark D. Pickerill for Pro-Log Corp. 9 Aug. 1988 *
- ;* Assemble with the 2500 A.D. X8086 assembler. *
- ;* *
- ;************************************************************************
- ;
- CR: EQU 0DH ; Carriage return
- LF: EQU 0AH ; Line feed
- EOF: EQU 1AH ; End of file
- ;
- ORG 0100H ; Start of tpa
- ;
- UNLOAD: JMP SHORT START ; Skip data area
- ;
- FILDAT: DB 0FFH ; Data to fill empty space in rom (if selected)
- BNPFTYP:DB 'PN' ; Pn for bnpf, hl for bhlf, or 10 for b10f
- FTYPE: DB '.HEX',00H ; File type
- FTYPE1: DB '.BNP',00H ; File type for bnpf files
- OUTTYPE:DB 00H ; 00 for hex, non-zero for bnpf
- USEEXT: DB 00H ; 00 for no extended address records
- DOFILL: DB 00H ; 00 not to fill to end of rom
- ENDSEG: DW 0000H ; Space to store end segment for rom fill
- ENDADDR:DW 0000H ; Space to store end address for rom fill
- OOD: DB 00H ; Flag 0 for read from disk, ff to use fildat
- NOPARMS:JMP HELP ; Extend short jump
- ;
- START: PUSH CS ; Set data segment
- POP DS ; It's set
- PUSH DS ; Get this segment
- POP ES ; And set es as well
- CALL ILPRT ; Print signon message
- DB CR,LF,'UNLOAD86 ver. 1.0',00H
- MOV SI,0080H ; Point to parameter field in psp
- MOV CL,[SI] ; Get parameter length
- OR CL,CL ; Force flags
- JZ NOPARMS ; Print help screen
- MOV CH,00H ; Zero ch
- LOOP1: INC SI ; Point to start of parameters
- MOV AL,[SI] ; Get byte from parameter field
- CMP AL,' ' ; Space?
- LOOPZ LOOP1 ; Wait until you get a non-space char
- JZ NOPARMS ; Just spaces, print help screen
- CMP AL,'/' ; Switch char?
- JZ NOPARMS ; No filename!, print help screen
- LEA DI,INFN ; Point to input filename area
- MOV [DI],AL ; Stuff this char
- LOOP2: INC SI ; Increment source
- INC DI ; And destination
- MOV AL,[SI] ; Get byte
- CMP AL,' ' ; End?
- JZ CONT ; Yes
- CMP AL,'/' ; Or switch char?
- JZ SWITCH ; Yes
- MOV [DI],AL ; Stuff char
- LOOP LOOP2 ; Nope
- JMP SHORT CONT ; No more
- SWITCH: INC SI ; Point to next
- MOV AL,[SI] ; Get switch options
- AND AL,5FH ; Make upper case as ibm types
- ; Usualy use lower case!
- CMP AL,'B' ; Bnpf option?
- JZ SETBNPF ; Yes
- CMP AL,'E' ; Use extended address records?
- JZ SETEXT ; Yes
- CMP AL,'P' ; Set eprom type?
- JZ SETROM ; Yes
- LOOP SWITCH ; Look for more options
- JMP CONT ; No more
- ;
- SETEXT: MOV AL,0FFH ; Indicate use of extended addressing
- MOV [USEEXT],AL ; Flag it as such
- LOOP SWITCH ; Look for more options
- JMP CONT ; No more
- ;
- SETBNPF:MOV AL,0FFH ; Indicate bnpf option
- MOV [OUTTYPE],AL ; Set it
- ;
- LOOKMOR:LOOP SWITCH ; If more, look for additional options
- JMP CONT ; No more
- ;
- SETROM: INC SI ; Look at next char
- DEC CX ; And decrement loop counter
- MOV AL,[SI] ; Get char
- CMP AL,'0' ; At least a zero?
- JC LOOKMOR ; No,ignore
- CMP AL,'A' ; At least an a?
- JC NUM ; Numeric
- AND AL,5FH ; Force upper case
- CMP AL,'G' ; More garbage?
- JNC LOOKMOR ; Yes, ignore
- SUB AL,37H ; Remove alpha bias
- JMP SHORT FOUNDIT ; And continue
- NUM: CMP AL,3AH ; Above numeric?
- JNC LOOKMOR ; Yes, ignore
- SUB AL,30H ; Remove numeric bias
- FOUNDIT:PUSH AX ; Save our number
- CMP AL,0CH ; Big rom?
- JC SMALL ; No
- MOV AL,0FFH ; Larger than 64k, force extended addressing
- MOV [USEEXT],AL ; Do it
- SMALL: POP AX ; Recover our number
- PUSH SI ; Save pointer
- LEA SI,ATABLE ; Point to address table
- ADD AL,AL ; Multiply by two
- ADD AL,AL ; And by four
- XOR AH,AH ; Clear ah
- ADD SI,AX ; Add in offset
- MOV AX,[SI] ; Get segment address
- MOV [ENDSEG],AX ; Stuff it
- ADD SI,02H ; Point to offset address
- MOV AX,[SI] ; Get offset address
- MOV [ENDADDR],AX ; Stuff it
- MOV [DOFILL],BYTE PTR 0FFH ; Flag fillrom operation
- POP SI ; Restore si
- JMP LOOKMOR ; Go look for more options
- ;
- CONT: INC DI ; Point past new filename
- MOV [DI],BYTE PTR 00H ; Terminate string
- LEA SI,INFN ; Copy input to output fn
- LEA DI,OUTFN ; Pointing to output filename
- MOV CX,60D ; 64-4 for 'hex0' is 60
- LOOP3: MOV AL,[SI] ; Get byte
- MOV [DI],AL ; Go ahead & move it
- INC SI ; Increment source
- INC DI ; And destination
- CMP AL,'.' ; Looking for that file extension
- JZ DONE ; Found the dot
- CMP AL,'0' ; End?
- LOOPNZ LOOP3 ; Continue
- DONE: DEC DI ; Backup over dot or zero
- MOV CX,0005H ; Five bytes to move
- MOV AL,[OUTTYPE] ; Hex or bnpf?
- OR AL,AL ; Force flags
- JZ OHEX ; Hex
- LEA SI,FTYPE1 ; Point to file type for bnpf
- JMP SHORT ALL ; And continue
- OHEX: LEA SI,FTYPE ; Point to file type for hex
- ALL: REP MOVSB ; Move the rest
- ;
- MOV AL,00H ; Read access code
- MOV AH,3DH ; Open file function
- LEA DX,INFN ; Point to input file name
- INT 21H ; Open the file
- MOV [INHDL],AX ; Save handle
- JNC OK ; Ok
- CALL ILPRT ; Print this...
- DB CR,LF,'Failure to Open Input file',00H
- JMP FINIS ; Go to error handler
- ;
- OK: MOV CL,00H ; Normal addributes
- MOV AH,3CH ; Create file function
- LEA DX,OUTFN ; Point to file name
- INT 21H ; Open the file
- JNC OK1 ; Ok
- CALL ILPRT ; Print this...
- DB CR,LF,'Failure to Open output file',00H
- JMP FINIS ; Go to error handler
- OK1: MOV [OUTHDL],AX ; Save handle
- MOV AL,[OUTTYPE] ; Get output format
- OR AL,AL ; Force flags
- JZ READ ; Don't do start char for bnpf
- LEA DX,CNTRLB ; Point to start byte
- MOV BX,[OUTHDL] ; Get output handle
- MOV AH,40H ; Write function
- MOV CX,0003H ; One byte + crlf
- INT 21H ; Do it
- JNC READ ; Ok
- JMP BADWR ; Error
- ;
- READ: LEA DI,INBUF ; Point to input buffer
- MOV CX,16D ; Fill entire buffer
- MOV AL,[FILDAT] ; Get fill data
- MOV AH,AL ; Dup into ah
- REP STOSW ; Do it
- ;
- MOV AL,[OOD] ; Already out of data?
- OR AL,AL ; Force flags
- JNZ FILLIT ; Yup
- LEA DX,INBUF ; Point to buffer
- MOV CX,32D ; Process 32 bytes at a time
- MOV BX,[INHDL] ; Get handle
- MOV AH,3FH ; Read function
- INT 21H ; Do it
- JNC ROK ; Ok
- CALL ILPRT ; Print this...
- DB CR,LF,'Error Reading Input file',00H
- JMP FINIS ; Go to error handler
- ;
- CNTRLB: DB 02H,CR,LF ; Bnpf start
- ;
- ROK: CMP AX,0000H ; Completely finished?
- JNZ NOPE ; Nope
- MOV AL,[OUTTYPE] ; Check for bnpf
- OR AL,AL ; Force flags
- JNZ EXIT ; Bnpf ignores all this...
- MOV AL,0FFH ; Indicate we're finished reading from disk
- MOV [OOD],AL ; Flag it
- MOV AL,[DOFILL] ; Check for fillrom function
- OR AL,AL ; Force flags
- JZ EXIT ; Not selected
- FILLIT: MOV AX,[EXTEND] ; Get current segment
- SUB AX,1000H ; Compensate to what is in use
- CMP [ENDSEG],AX ; Check against selected end segment
- JC TOOBIG ; Warn operator that his data won't fit
- JNZ NOPE ; Segment hasn't been reached yet, continue
- MOV AX,[ADDRESS] ; Get current address
- DEC AX ; To last location, not next avail loc
- CMP [ENDADDR],AX ; Check against selected end address
- JC TOOBIG ; Warn oerator that his data won't fit
- JNZ NOPE ; Address hasn't been reached yet
- ;
- EXIT: JMP FINISHUP ; Yes, finish up & terminate
- TOOBIG: JMP WARN ; Tell operator
- NOPE: MOV AL,[OUTTYPE] ; Get output format
- OR AL,AL ; Force flags
- JZ HEX ; Do hex
- ; Drop through to bnpf
- LEA SI,INBUF ; Point to input buffer
- MOV CX,32D ; 32 bytes to process
- BNPF: LEA DI,OUTBUF ; Output buffer
- MOV [DI],BYTE PTR 'B' ; The b for begin
- INC DI ; Next location
- BIGLP: MOV AL,[SI] ; Get byte
- PUSH CX ; Save byte loop
- MOV CX,0008H ; 8 bits in a byte
- BNPFLP: RCL AL,1 ; Rotate through carry
- JC P ; High
- MOV AH,[BNPFTYP]+1 ; Get the byte for low
- MOV [DI],AH ; Put in buffer
- INC DI ; Next location
- LOOP BNPFLP ; Do entire byte
- JMP ONEBYTE ; Complete & write
- P: MOV AH,[BNPFTYP] ; Get the byte for high
- MOV [DI],AH ; Put in buffer
- INC DI ; Next location
- LOOP BNPFLP ; Do entire byte
- ONEBYTE:MOV [DI],BYTE PTR 'F' ; The f for finish
- POP CX ; Recover byte loop
- INC SI ; Next byte
- INC DI ; Next dest
- MOV [DI],BYTE PTR 0DH ; Send a cr
- INC DI ; Next
- MOV [DI],BYTE PTR 0AH ; Send a lf
- INC DI ; Next
- PUSH CX ; Save loop counter
- PUSH SI ; Save input counter
- MOV CX,12D ; Twelve bytes every time
- CALL WRITE ; Write byte
- POP SI ; Recover input counter
- POP CX ; Recover loop counter
- LOOP BNPF ; Do next byte
- JMP READ ; Read next 32 bytes
- ;
- HEX: XOR BX,BX ; Output counter
- MOV CX,32D ; Input counter
- XOR DX,DX ; Dl is checksum reg
- MOV AX,[ADDRESS] ; Get current load address
- OR AX,AX ; Force flags
- JNZ NOEXT ; No extended address record needed
- CALL EAR ; Do extended addressing if selected
- NOEXT: LEA SI,INBUF ; Point to input buffer
- LEA DI,OUTBUF ; Point to output buffer
- MOV [DI],BYTE PTR ':' ; Stuff that colon
- INC DI ; And point to next
- INC BX ; And increment counter
- MOV AL,20H ; All are 32 byte records
- CALL BITE ; Stuff it
- MOV AX,[ADDRESS] ; Get load address
- XCHG AL,AH ; Do high byte first
- CALL BITE ; Send it
- XCHG AH,AL ; Now do low byte
- CALL BITE ; Send it
- MOV AX,[ADDRESS] ; Get load address
- ADD AX,20H ; Increment to next
- MOV [ADDRESS],AX ; Put back
- MOV AL,00H ; Record type 00
- CALL BITE ; Send it
- LOOP4: MOV AL,[SI] ; Get input
- CALL BITE ; Process
- INC SI ; Point to next
- LOOP LOOP4 ; Until done
- MOV AL,DL ; Get checksum
- CALL BITE ; Process, [clobbering dl]
- MOV [DI], WORD PTR 0A0DH ; Append crlf
- ADD BX,02H ; Bump output counter appropiately
- MOV CX,BX ; Get count into cx
- CALL WRITE ; Write output
- JMP READ ; Read more
- ;
- WRITE: LEA DX,OUTBUF ; Point to beginning of output buffer
- MOV BX,[OUTHDL] ; Get output handle
- MOV AH,40H ; Write function
- INT 21H ; Do it
- JNC WOK ; Ok
- BADWR: CALL ILPRT ; Print this...
- DB CR,LF,'Error Writing Output file',00H
- JMP FINIS ; Go to error handler
- WOK: RET ; Near
- ;
- EAR: PUSH AX ; Save everything
- MOV AL,[USEEXT] ; Get extended address flag
- OR AL,AL ; Force flags
- JNZ GOAHEAD ; Yes, do extended addressing
- MOV AX,[EXTEND] ; Get extended address anyway
- ADD AX,1000H ; Increment to next 64k block
- MOV [EXTEND],AX ; Put back for consistancy
- POP AX ; Restore ax
- RET ; Go home
- GOAHEAD:PUSH DI ;
- PUSH CX ;
- PUSH DX ;
- PUSH SI ;
- PUSH BX ;
- LEA DI,OUTBUF ; Point to output buffer
- MOV [DI],BYTE PTR ':' ; Stuff that colon
- INC DI ; And point to next
- INC BX ; And increment counter
- MOV AL,02H ; Two bytes of data in extended record
- CALL BITE ; Stuff it
- MOV AX,0000H ; Extended address records have load addr of 0
- XCHG AL,AH ; Do high byte first
- CALL BITE ; Send it
- XCHG AH,AL ; Now do low byte
- CALL BITE ; Send it
- MOV AL,02H ; Record type 02
- CALL BITE ; Send it
- MOV AX,[EXTEND] ; Get current extended address
- XCHG AL,AH ; Do high byte first
- CALL BITE ; Send it
- XCHG AH,AL ; Now do low byte
- CALL BITE ; Send it
- MOV AX,[EXTEND] ; Get extended address again
- ADD AX,1000H ; Increment to next 64k block
- MOV [EXTEND],AX ; Put back
- MOV AL,DL ; Get checksum
- CALL BITE ; Process, [clobbering dl]
- MOV [DI], WORD PTR 0A0DH ; Append crlf
- ADD BX,02H ; Bump output counter appropiately
- MOV CX,BX ; Get count into cx
- CALL WRITE ; Write output
- POP BX ; Recover everything
- POP SI ;
- POP DX ;
- POP CX ;
- POP DI ;
- POP AX ;
- RET ; Go home
- ;
- FINISHUP: ;
- CALL ILPRT ; Print this...
- DB CR,LF,'Function Complete.',00H
- MOV AL,[OUTTYPE] ; Get output format
- OR AL,AL ; Force flags
- JZ HEXEND ; Do hex
- ; Drop through to bnpf
- ;
- BNPFEND:LEA DX,CNTRLC ; Point to eof marker
- MOV BX,[OUTHDL] ; Get output handle
- MOV AH,40H ; Write function
- MOV CX,0003H ; One byte
- INT 21H ; Do it
- JNC WOKK ; Ok
- JMP BADWR ; Error
- ;
- WARN: CALL ILPRT ; Print this...
- DB CR,LF,LF,'WARNING: Input data file too large for output size'
- DB ' selected.',07H,LF,00H ;
- JMP FINISHUP ; Terminate
- ;
- CNTRLC: DB 03H,CR,LF ; Termination for bnpf
- ;
- HEXEND: LEA DX,EOFREC ; Point to eof record
- MOV BX,[OUTHDL] ; Get output handle
- MOV AH,40H ; Write function
- MOV CX,0014H ; Fourteen bytes
- INT 21H ; Do it
- JNC WOKK ; Ok
- JMP BADWR ; Error
- ;
- WOKK: MOV AH,3EH ; Close the file now
- MOV BX,[OUTHDL] ; Close output
- INT 21H ; Close the damn thing
- JNC CLOK ; Closed ok
- CALL ILPRT ; Print this...
- DB CR,LF,'Error Closing Output file!',00H
- ;
- CLOK: MOV AH,3EH ; Close the file now
- MOV BX,[INHDL] ; Close input
- INT 21H ; Close the damn thing
- JNC FINIS ; Closed ok
- CALL ILPRT ; Print this...
- DB CR,LF,'Error Closing Input file!',00H
- ;
- FINIS: MOV AX,4C00H ; Terminate
- INT 21H ; Bye-bye
- ;
- EOFREC: DB ':00000001FF',CR,LF,EOF ; End of file record
- ;
- ;************************************************************************
- ;* *
- ;* ILPRT: This is an 8088 in-line print routine. It will print *
- ;* the string following the CALL NEAR instruction until a 00H is *
- ;* encountered. Accepts: Data string to print in memory following*
- ;* the CALL NEAR used to invoke this routine. Returns: Nothing. *
- ;* Calls: CONOUT. Clobbers: ES,SI *
- ;* *
- ;************************************************************************
- ;
- ILPRT: PUSH CS ; Get code segment
- POP ES ; Into es
- POP SI ; Get offset
- PUSH AX ; Save ax
- PUSH DX ; And dx
- ILLP: MOV AL,ES:[SI] ; Get char
- OR AL,AL ; Force flags
- JZ ILEXIT ; Exit if last
- CALL CONOUT ; Send char
- INC SI ; Point to next
- JMP SHORT ILLP ; Loop til done
- ILEXIT: INC SI ; Point to next instruction
- POP DX ; Restore dx
- POP AX ; And ax
- PUSH SI ; And return offset
- RET ; Near
- ;
- CONOUT: MOV AH,02H ; Conout call
- MOV DL,AL ; Get char
- INT 21H ; Do it
- RET ; Near
- ;
- BITE: SUB DL,AL ; Generate checksum
- PUSH AX ; Save
- AND AL,0F0H ; Mask out lower nybble
- ROR AL,1 ; Get msn into lower nybble
- ROR AL,1 ;
- ROR AL,1 ;
- ROR AL,1 ; Now it's there
- CALL NYB ; Process nybble
- MOV [DI],AL ; Save in disk buffer
- INC BX ; Increment count
- INC DI ; Next location in buffer
- POP AX ; Recover byte
- AND AL,0FH ; Mask lsn
- CALL NYB ; Process nybble
- MOV [DI],AL ; Save in disk buffer
- INC BX ; Increment count
- INC DI ; Next location in buffer
- RET ; Near
- ;
- ; Converts lower nybble in al to ascii hex
- NYB: CMP AL,0AH ; Letter?
- JNC NYB1 ; Yes
- ADD AL,30H ; Add in numeric bias
- RET ; Go home (near)
- NYB1: ADD AL,37H ; Add in letter bias
- RET ; Go home (near)
- ;
- INHDL: BLKB 2 ; Storage for input file handle
- OUTHDL: BLKB 2 ; Storage for output file handle
- ADDRESS:DW 0000H ; Current address
- EXTEND: DW 0000H ; Current extended address
- INFN: BLKB 64D ; Plenty of room for a filename & path
- OUTFN: BLKB 64D ; Output filename
- INBUF: BLKB 32D ; Thirty two byte input buffer
- OUTBUF: EQU $ ; Output buffer
- ;
- HELP: ; Called only if nothing is going to happen
- ; Otherwise, this routine is overwritten
- CALL ILPRT ; Print help screen
- DB CR,LF,LF,'Usage: UNLOAD86 FILENAME.TYP[/OPTIONS]'
- DB CR,LF,LF,'Where Options are:'
- DB CR,LF,' B for BNPF instead of INTeL hex.'
- DB '(Overrides all other options!)'
- DB CR,LF,' E to use extended addressing in INTeL hex.'
- DB CR,LF,' P to fill output file to end of EPROM.'
- DB CR,LF,' Uses the following subcommands:'
- DB CR,LF,' 0 32 Bytes 1 64 Bytes'
- DB CR,LF,' 2 128 Bytes 3 256 Bytes'
- DB CR,LF,' 4 512 Bytes 5 1K Bytes'
- DB CR,LF,' 6 2K Bytes 7 4K Bytes'
- DB CR,LF,' 8 8K Bytes 9 16K Bytes'
- DB CR,LF,' A 32K Bytes B 64K Bytes'
- DB CR,LF,' C *128K Bytes D *256K Bytes'
- DB CR,LF,' E *512K Bytes F *1Meg Bytes'
- DB CR,LF,LF,' * Forces extended addressing'
- DB CR,LF,LF,'INTeL hex output files are .HEX'
- DB CR,LF,'BNPF output files are .BNP'
- DB CR,LF,00H ;
- JMP FINIS ; Terminate
- ;
- ATABLE: ; Table of rom sizes for fillrom option
- DW 0000H ; Segment for 32 byter
- DW 001FH ; Address for 32 byter
- DW 0000H ; Segment for 64 byter
- DW 003FH ; Address for 64 byter
- DW 0000H ; Segment for 128 byter
- DW 007FH ; Address for 128 byter
- DW 0000H ; Segment for 256 byter
- DW 00FFH ; Address for 256 byter
- DW 0000H ; Segment for 512 byter
- DW 01FFH ; Address for 512 byter
- DW 0000H ; Segment for 1k byter
- DW 03FFH ; Address for 1k byter
- DW 0000H ; Segment for 2k byter
- DW 07FFH ; Address for 2k byter
- DW 0000H ; Segment for 4k byter
- DW 0FFFH ; Address for 4k byter
- DW 0000H ; Segment for 8k byter
- DW 1FFFH ; Address for 8k byter
- DW 0000H ; Segment for 16k byter
- DW 3FFFH ; Address for 16k byter
- DW 0000H ; Segment for 32k byter
- DW 7FFFH ; Address for 32k byter
- DW 0000H ; Segment for 64k byter
- DW 0FFFFH ; Address for 64k byter
- DW 1000H ; Segment for 128k byter
- DW 0FFFFH ; Address for 128k byter
- DW 3000H ; Segment for 256k byter
- DW 0FFFFH ; Address for 256k byter
- DW 7000H ; Segment for 512k byter
- DW 0FFFFH ; Address for 512k byter
- DW 0F000H ; Segment for 1m byter
- DW 0FFFFH ; Address for 1m byter
- ;
- END ;