Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 3.X/CPM 3.0/SOURCE/hexcom.asm
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

663 lines
16 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

title 'CP/M 3 - HEXCOM - Oct 1982'
;
; Copyright (C) 1982
; Digital Research
; P.O. Box 579
; Pacific Grove, CA 93950
; Revised:
; 22 Oct 82 by Paul Lancaster
; 25 Oct 82 by Doug Huskey
;
;
; ********** HEXCOM **********
;
;PROGRAM TO CREATE A CP/M "COM" FILE FROM A "HEX" FILE.
;THIS PROGRAM IS VERY SIMILAR IN FUNCTION TO THE CP/M
;UTILITY CALLED "LOAD". IT IS OPTIMIZED WITH RESPECT TO
;EXECUTION SPEED AND MEMORY SPACE. IT RUNS ABOUT TWICE
;AS FAST AS THE CP/M COUNTERPART ON A LONG "HEX" FILE.
;IT IS ALSO ABOUT 700 BYTES SHORTER.
;ONE MINOR DIFFERENCE BETWEEN "HEXCOM" AND "LOAD" THAT MAY
;BE VISIBLE TO THE USER IS THAT VERY LARGE LOAD ADDRESS
;INVERSIONS ARE TOLERATED BY "HEXCOM", WHEREAS THE MAXIMUM
;ALLOWED INVERSION IN "LOAD" IS 80H. THE MAXIMUM IN "HEXCOM"
;IS A FUNCTION OF THE TPA SIZE.
;CAUTION SHOULD BE EXERCIZED WHEN USING AN INVERSION GREATER
;THAN 80H IN "HEXCOM" SINCE PART OF THE COMFILE MAY NOT
;GET CREATED IF THE FINAL LOAD ADDRESS IS INVERTED WITH
;RESPECT TO THE "LAST ADDRESS" IN THE "HEX" FILE.
;*******************************************************
;VERSION 1.00 6 MARCH 1979
;ORIGINAL VERSION.
;*******************************************************
;22 October 1982 - Changed assumed CCP length for CP/M-PLUS
;25 October 1982 - Changed version to 3.0
;
;
EQUATES
VERS EQU 300 ;VERSION TIMES 100
CR EQU 0DH
LF EQU 0AH
BDOS EQU 5
DEFAULT$FCB EQU 5CH
ORG 100H
; include file for use with ASM programs
;
;*********************************************
;* STANDARD DIGITAL RESEARCH COM FILE HEADER *
;*********************************************
;
JMP BEGIN ;LABEL CAN BE CHANGED
;
;*********************************************
;* Patch Area, Date, Version & Serial Number *
;*********************************************
;
dw 0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
db 0
db 'CP/M Version 3.0'
maclib makedate ;[JCE] Build date
@LCOPY
@BDATE ; version date day-month-year
db 0,0,0,0 ; patch bit map
db '654321' ; Serial no.
;
BEGIN:
; code starts here
LXI H,0
DAD SP ;GET CURRENT CCP STACK
SHLD STACK$SAVE ;SAVE IT
LXI SP,STACK ;INIT LOCAL STACK
LXI D,SIGNON$MSG ;POINT SIGN-ON MESSAGE
CALL PRINT$BUFFER ;SEND IT TO CONSOLE
LXI D,DEFAULT$FCB ;FILE NAME TO HEX FCB
LXI H,HEX$FCB
PUSH D ;SAVE COM FCB ADDR
PUSH H ;-AND HEX FCB ADDR
MVI C,33 ;MOVE ENTIRE FCB
MOVEFCB LDAX D ;GET BYTE FROM DFLT FCB
MOV M,A ;MOVE TO HEX FCB
INX D ;BUMP POINTERS
INX H
DCR C ;HIT COUNTER
JNZ MOVEFCB ;LOOP TILL DONE
LXI H,HEX$FCB+9 ;"HEX" TYPE NAME TO FCB
MVI M,'H'
INX H
MVI M,'E'
INX H
MVI M,'X'
LXI H,DEFAULT$FCB+9 ;"COM" TYPE NAME TO FCB
MVI M,'C'
INX H
MVI M,'O'
INX H
MVI M,'M'
POP D ;HEX$FCB TO <DE>
MVI C,15 ;OPEN FILE
CALL BDOS
INR A ;SEE IF -1 FOR ERROR
LXI D,COSMSG
JZ ERROR$ABORT ;CANNOT OPEN SOURCE
POP D ;COM FCB ADDR
PUSH D ;KEEP COPY ON STACK
MVI C,19 ;DELETE FILE
CALL BDOS ;DELETE OLD "COM" FILE
POP D ;GET COM FCB ADDR AGAIN
PUSH D ;SAVE IT STILL
MVI C,22 ;MAKE FILE
CALL BDOS ;CREATE "COM" FILE
INR A ;SEE IF -1 FOR ERROR
LXI D,NMDSMSG
JZ ERROR$ABORT ;NO MORE DIR SPACE
;DEFINE AND CLEAR THE COMFILE BUFFER
LDA 7 ;GET BDOS PAGE ADDRESS
SUI 16 ;ALLOW FOR UP TO 4K CCP
MOV H,A ;HI BYTE OF COM BUFFER TOP
MVI L,0 ;END ON PAGE BOUNDARY
SHLD CURR$COM$BUF$END
SUI (HIGH COMFILE$BUFFER)+1
MVI L,80H ;START IN MIDDLE OF PAGE
MOV H,A ;BUFFER LENGTH IN PAGES
SHLD CURR$COM$BUF$LEN
CALL CLEAR$COMBUFFER ;ZERO-OUT COM BUFFER
; HEX RECORD LOOP
SCAN$FOR$COLON:
CALL GET$HEXFILE$CHAR
CPI ':' ;DO WE HAVE COLON YET?
JNZ SCAN$FOR$COLON
CALL GET$BINARY$BYTE ;GOT COLON. GET LOAD COUNT
STA LOAD$COUNT ;STORE COUNT FOR THIS RECORD
JZ FINISH$UP ;ZERO MEANS ALL DONE
;INCREMENT BYTES-READ COUNTER BY NUMBER OF BYTES TO BE
;LOADED IN THIS RECORD.
LXI H,BYTES$READ$COUNT
ADD M ;ADD LO BYTE OF SUM
MOV M,A ;SAVE NEW LO BYTE
JNC FORM$LOAD$ADDRESS
INX H ;POINT HI BYTE OF SUM
INR M ;BUMP HI BYTE
;NOW SET NEW LOAD ADDRESS FROM THE
;HEX FILE RECORD.
FORM$LOAD$ADDRESS:
CALL GET$BINARY$BYTE
PUSH PSW
CALL GET$BINARY$BYTE
POP H ;HI BYTE TO <H>
MOV L,A ;AND LO BYTE TO <L>
SHLD LOAD$ADDRESS ;SAVE NEW LOAD ADDRESS
XCHG ;PUT IN <DE>
LHLD CURRENT$COM$BASE
;NEW LOAD ADDRESS MINUS THE CURRENT COMFILE BASE GIVES
;THE NEW COM BUFFER OFFSET.
MOV A,E
SUB L
MOV L,A
MOV A,D
SBB H
MOV H,A
SHLD COM$BUF$OFFSET ;STORE NEW OFFSET
LXI D,ILAMSG ;POINT ERR MSG
JC ERROR$ABORT ;FATAL INVERSION IF CY SET
;FIRST ADDRESS HAS ALREADY BEEN ESTABLISHED IF "FIRST$ADDRESS"
;IS NON-ZERO.
LDA FIRST$ADDRESS+1 ;--ONLY PAGE NO. NEED BE
ORA A ;--CHECKED SINCE 1ST ADDR
JNZ GET$ZERO$BYTE ;--CAN'T BE IN PAGE ZERO
LXI D,FAMSG ;POINT "1ST ADDR" MSG
CALL MSG$ON$NEW$LINE ;ANNOUNCE FIRST ADDRESS
LHLD LOAD$ADDRESS ;THIS IS FIRST ADDR
SHLD FIRST$ADDRESS ;SET FIRST ADDRESS
CALL WORD$OUT ;SEND IT TO CONSOLE
;SKIP OVER THE ZERO BYTE OF THE HEX RECORD. IT HAS NO
;SIGNIFICANCE TO THIS PROGRAM.
GET$ZERO$BYTE:
CALL GET$BINARY$BYTE
;THIS LOOP LOADS THE COM FILE WITH THE BYTE VALUES IN THE
;CURRENT HEX RECORD.
BYTE$LOAD$LOOP:
CALL GET$BINARY$BYTE ;GET BYTE TO LOAD
CALL PUT$TO$COMFILE ;LOAD IT TO COM FILE
LXI H,LOAD$COUNT
DCR M ;HIT LOAD COUNT
JNZ BYTE$LOAD$LOOP ;MORE LOADING IF NOT-ZERO
;UPDATE THE LAST ADDRESS IF CURRENT ABSOLUTE LOAD ADDRESS
;IS HIGHER THAN THE CURRENT VALUE OF "LAST$ADDRESS"
LHLD LAST$ADDRESS ;GET THE CURR VALUE
XCHG ;TO <DE>
CALL ABSOLUTE ;ABSOLUTE ADDR TO <HL>
MOV A,E ;--SUBTRACT ABSOLUTE
SUB L ;--ADDRESS FROM CURRENT
MOV A,D ;--LAST ADDRESS
SBB H
JNC CHECK$CHECKSUM ;LAST ADDR LARGER IF NC
DCX H ;DOWN 1 FOR LAST ACTUAL LOAD
SHLD LAST$ADDRESS ;UPDATE IT
;VERIFY THE CHECKSUM FOR THIS RECORD.
CHECK$CHECKSUM:
CALL GET$BINARY$BYTE ;GET CHECKSUM BYTE
JZ SCAN$FOR$COLON ;ZERO ON FOR CHECKSUM OK
LXI D,CSEMSG ;CHECKSUM ERROR
JMP HEXFILE$ERROR
;SEND PROCESSING SUMMARY TO THE CONSOLE AND FLUSH THE
;COM BUFFER OF ANY UNWRITTEN DATA.
FINISH$UP:
LXI D,LSTADDRMSG ;POINT "LAST ADDR" MSG
CALL MSG$ON$NEW$LINE ;SEND IT OUT
LHLD LAST$ADDRESS ;GET THE LAST ADDRESS
CALL WORD$OUT ;SEND IT TO CONSOLE
LXI D,BRMESSAGE ;POINT "BYTES READ" MSG
CALL MSG$ON$NEW$LINE ;SEND IT OUT
LHLD BYTES$READ$COUNT ;GET THE COUNT
CALL WORD$OUT ;SEND IT OUT
;THE FOLLOWING CODE PREPARES FOR AND MAKES THE FINAL CALL
;TO THE "PUT" ROUTINE IN ORDER TO FLUSH THE "COM" BUFFER.
;IT HAS BEEN "KLUGED" IN ORDER TO WORK AROUND THE BOUNDARY
;CONDITION OF HAVING AN OFFSET OF <100H AT FLUSH TIME.
;WE FORCE THE OFFSET AND LENGTH TO BE NON-ZERO SO THE
;INITIAL COMPARE IN THE "PUT" ROUTINE WON'T GET SCREWED
;UP. THE BUFFER END ADDRESS IS NOT PLAYED WITH, HOWEVER.
;THIS IS TO INSURE THAT THE CORRECT NUMBER OF RECORDS GET
;WRITTEN.
LHLD COM$BUF$OFFSET ;GET THE CURRENT OFFSET
PUSH H ;SAVE OFFSET FOR LATER
LXI D,COMFILE$BUFFER ;GET BUFFER ADDRESS
DAD D ;ADD TO OFFSET TO GET LEN
SHLD CURR$COM$BUF$END ;STORE NEW END ADDR
LXI H,CLEAR$FLAG ;POINT TO CLEAR FLAG
INR M ;DISABLE CLEAR WITH NON-ZERO
POP H ;GET OFFSET BACK
MVI H,1 ;FORCE HI BYTE NON-ZERO
SHLD COM$BUF$OFFSET ;FAKE OFFSET
SHLD CURR$COM$BUF$LEN ;AND FAKE LENGTH
CALL PUT$TO$COMFILE ;FLUSH THE BUFFER
LXI D,RWMSG ;POINT "REC WRIT" MSG
CALL MSG$ON$NEW$LINE ;SEND IT OUT
LDA RECORDS$WRITTEN ;GET THE COUNT
CALL BYTE$OUT ;SEND IT OUT
CALL CRLF ;SEND OUT CRLF
POP D ;COM FILE FCB ADDR
MVI C,16 ;CLOSE FILE
CALL BDOS ;COM FILE CLOSE
INR A ;SEE IF -1 FOR ERROR
LXI D,CCFMSG ;CANNOT CLOSE FILE
JZ ERROR$ABORT
CRLF$AND$EXIT:
CALL CRLF
EXIT:
LXI D,80H
MVI C,26 ;RE-SET DMA TO 80H
CALL BDOS
LHLD STACK$SAVE ;RECOVER CCP STACK POINTER
SPHL ;TO <SP>
RET ;RET TO CCP
; SUBROUTINES
;THIS ROUTINE GETS TWO CHARACTERS FROM THE HEX FILE
;AND CONVERTS TO AN 8-BIT BINARY VALUE, RETURNED IN <A>.
GET$BINARY$BYTE:
CALL GET$HEX$DIGIT ;GET HI NYBBLE FIRST
ADD A ;SHIFT UP 4 SLOTS
ADD A
ADD A
ADD A
PUSH PSW ;SAVE HI NYBBLE
CALL GET$HEX$DIGIT ;NOW GET LO NYBBLE
POP B ;HI NYBBLE TO <B>
ORA B ;COMBINE NYBBLES TO FORM BYTE
MOV B,A ;SAVE THE BYTE
LXI H,CHECKSUM
ADD M ;UPDATE THE CHECKSUM
MOV M,A ;AND STORE IT
MOV A,B ;GET BYTE BACK
RET ;ZERO SET MEANS CHECKSUM=0
;ROUTINE TO GET A HEX-ASCII CHARACTER FROM THE HEX FILE
;AND RETURN IT IN THE <A> REGISTER CONVERTED TO BINARY.
;A CHECK FOR LEGAL HEX VALUE IS MADE. PROGRAM ABORTS
;WITH APPROPRIATE MESSAGE IF ILLEGAL DIGIT ENCOUNTERED.
GET$HEX$DIGIT:
CALL GET$HEXFILE$CHAR
SUI '0' ;REMOVE ASCII BIAS
CPI 10 ;DECIMAL DIGIT?
RC
SUI 7 ;STRIP ADDITIONAL BIAS
CPI 10 ;MUST BE AT LEAST 10
JC ILLHEX
CPI 16 ;MUST BE 15 OR LESS
RC
ILLHEX LXI D,IHDMSG ;ILLEGAL HEX DIGIT
;ROUTINE TO INDICATE THAT AN ERROR HAS BEEN FOUND IN THE
;HEX FILE (EITHER CHECKSUM OR ILLEGAL HEX DIGIT).
;APPROPRIATE MESSAGES ARE PRINTED AND THE PROGRAM ABORTS.
HEXFILE$ERROR:
CALL MSG$ON$NEW$LINE ;PRINT ERROR TYPE
LXI D,LAMESSAGE ;POINT "LOAD ADDR" MSG
CALL MSG$ON$NEW$LINE ;SEND IT OUT
LHLD LOAD$ADDRESS ;GET LOAD ADDR
CALL WORD$OUT ;SEND IT OUT
LXI D,EAMSG ;POINT "ERR ADDR" MSG
CALL MSG$ON$NEW$LINE ;SEND IT OUT
CALL ABSOLUTE ;GET ABSOLUTE ADDR
CALL WORD$OUT ;THIS IS ERR ADDR
LXI D,BRMESSAGE ;POINT "BYTES READ" MSG
CALL MSG$ON$NEW$LINE ;SEND IT OUT
CALL PRINT$LOAD$ADDR ;SEND OUT CURR LOAD ADDR
;PRINT OUT ALL BYTES THAT WERE LOADED FROM THE CURRENT
;HEX RECORD UP TO THE POINT WHERE THE ERROR WAS DETECTED.
ERR$OUT$LOOP:
LHLD LOAD$ADDRESS ;POINT TO BYTE TO BE OUTPUT
XCHG ;TO <DE>
CALL ABSOLUTE ;GET ABSOLUTE ADDR
MOV A,E ;--SEE IF "LOAD ADDR"
SUB L ;--HAS REACHED ABSO ADDR
MOV A,D
SBB H
JNC CRLF$AND$EXIT ;DONE IF THEY'RE EQUAL
MOV A,E ;SEE IF MULTIPLE OF 16
ANI 0FH
CZ PRINT$LOAD$ADDR ;IF MULTIPLE OF 16
LHLD LOAD$ADDRESS ;GET LOAD ADDR AGAIN
XCHG ;TO <DE>
LHLD CURRENT$COM$BASE
MOV A,E ;--CALC OFFSET OF CURR
SUB L ;--BYTE TO GO OUT
MOV L,A ;LO BYTE OF OFFSET
MOV A,D ;HI BYTE OF LOAD ADDR
SBB H
MOV H,A ;HI BYTE OF OFFSET
LXI B,COMFILE$BUFFER
DAD B ;<HL> NOW POINTS TO BYTE TO GO
MOV A,M ;GET THE BYTE FROM BUFFER
CALL BYTE$OUT ;SEND IT OUT
LHLD LOAD$ADDRESS ;BUMP LOAD ADDRESS
INX H
SHLD LOAD$ADDRESS
MVI A,' ' ;SEND A SPACE BETWEEN BYTES
CALL CHAR$TO$CONSOLE
JMP ERR$OUT$LOOP ;BACK FOR MORE
;ROUTINE TO GET A CHARACTER FROM THE HEX FILE BUFFER.
;CHAR IS RETURNED IN <A>.
GET$HEXFILE$CHAR:
LDA HEX$BUFFER$OFFSET
INR A ;BUMP HEX OFFSET
JP GETCHAR ;PLUS IF NOT 80H YET
LXI D,HEX$BUFFER
MVI C,26 ;SET-DMA CODE
CALL BDOS ;SET DMA ADDR TO HEX BUFFER
LXI D,HEX$FCB ;POINT HEX FCB
MVI C,20 ;READ-NEXT-RECORD CODE
CALL BDOS ;GET NEXT HEXFILE RECORD
ORA A ;TEST FOR ERROR
LXI D,DRMSG ;ASSUME ERROR FOR NOW
JNZ ERROR$ABORT ;FATAL ERR IF NOT ZERO
GETCHAR:
STA HEX$BUFFER$OFFSET
MVI H,HIGH HEX$BUFFER
MOV L,A ;POINT TO NEXT CHAR
MOV A,M ;GET THE CHARACTER
RET
;
;THIS ROUTINE PUTS A DATA BYTE TO THE "COM" FILE.
;THE BYTE IS PASSED IN <A>.
;THE FIRST COMPARE IS DONE ON JUST THE HI BYTES FOR THE
;SAKE OF SPEED, SINCE WE ARE PROCESSING THE "HEX" FILE
;"ON THE FLY".
PUT$TO$COMFILE:
PUSH PSW ;SAVE BYTE TO LOAD
LHLD COM$BUF$OFFSET ;GET CURRENT OFFSET
XCHG ;TO <DE>
PTC LDA CURR$COM$BUF$LEN+1 ;PAGE NO. OF BUFF TOP
DCR A ;ONE LESS FOR COMPARE
CMP D ;TOP < OFFSET?
JNC STORE$BYTE ;STORE BYTE IF NOT
LHLD CURR$COM$BUF$LEN
MOV A,E ;SUBTRACT LEN FROM OFFSET--
SUB L ;--TO GET NEW OFFSET
MOV C,A ;<C> HAS LO BYTE OF DIFF
MOV A,D ;HI BYTE OF OFFSET
SBB H ;MINUS HI BYTE OF BUFF LENGTH
MOV B,A ;<BC> HAS NEW OFFSET
PUSH B ;SAVE NEW OFFSET
XCHG ;BUFFER LENGTH TO <DE>
LHLD CURRENT$COM$BASE ;COM BASE TO <HL>
DAD D ;INCREASE IT BY BUFFER LENGTH
SHLD CURRENT$COM$BASE ;STORE NEW BASE
LHLD CURR$COM$BUF$END
LXI D,COMFILE$BUFFER ;BUFFER ADDR TO <DE>
COMLOOP:
MOV A,E ;SUBTRACT BUFF END FROM POINTER
SUB L
MOV A,D
SBB H ;WRITTEN TO END OF BUFFER YET?
JNC STORE ;CY OFF MEANS WE'RE DONE
PUSH H ;SAVE BUFFER END ADDRESS
PUSH D ;SAVE WRITE POINTER
MVI C,26 ;SET DMA FUNCTION CODE
CALL BDOS ;SET NEW DMA ADDRESS
MVI C,21 ;WRITE-NEXT-RECORD CODE
LXI D,DEFAULT$FCB ;POINT COM FILE FCB
CALL BDOS ;WRITE NEXT COM RECORD
ORA A ;TEST FOR ERROR ON WRITE
LXI D,DWMSG ;POINT WRITE ERROR MSG
JNZ ERROR$ABORT ;BOMB IF WRITE ERROR
POP D ;RESTORE WRITE POINTER
LXI H,128 ;SECTOR SIZE
DAD D ;BUMP POINTER BY 128
XCHG ;NEW POINTER TO <DE>
LXI H,RECORDS$WRITTEN
INR M
POP H ;RESTORE BUFFER END ADDR
JMP COMLOOP ;SEE IF END OF BUFFER YET
STORE:
LDA CLEAR$FLAG ;GET CLEAR-BUFFER FLAG
ORA A ;SHALL WE CLEAR?
CZ CLEAR$COMBUFFER ;ZERO THE BUFFER
POP D ;GET BACK NEW OFFSET
JMP PTC ;SEE IF WE MUST FLUSH AGAIN
STORE$BYTE:
LXI H,COMFILE$BUFFER ;BUFFER ADDR TO <HL>
DAD D ;ADD TO CURRENT OFFSET
POP PSW ;RETRIEVE BYTE TO WRITE
MOV M,A ;STUFF IT
INX D ;BUMP OFFSET
XCHG ;TO <HL> FOR STORE
SHLD COM$BUF$OFFSET ;UPDATE OFFSET
RET ;ALL DONE
;
;ROUTINE TO CONVERT THE 2-BYTE VALUE IN <HL> TO
;TWO ASCII CHARACTERS AND SEND THEM TO THE CONSOLE.
;
WORD$OUT:
PUSH H ;SAVE WORD
MOV A,H ;HI WORD GOES OUT 1ST
CALL BYTE$OUT
POP H ;RESTORE WORD
MOV A,L ;LO BYTE GOES NEXT
BYTE$OUT:
PUSH PSW ;SAVE BYTE
RRC! RRC! RRC! RRC ;HI NYBBLE COMES DOWN
CALL NYBBLE$OUT
POP PSW ;RESTORE VALUE
NYBBLE$OUT:
ANI 0FH
ADI 90H
DAA
ACI 40H
DAA
CHAR$TO$CONSOLE:
MOV E,A
MVI C,2 ;WRITE CONSOLE CHAR FUNC CODE
JMP BDOS
;
;ROUTINE TO OUTPUT A "CRLF".
;
CRLF:
MVI A,CR
CALL CHAR$TO$CONSOLE
MVI A,LF
JMP CHAR$TO$CONSOLE
;
;ROUTINE TO PRINT A BUFFER TO THE CONSOLE.
;<DE> POINTS TO THE MESSAGE ON ENTRY.
;EARLIEST ENTRY POINT STARTS MESSAGE ON A NEW LINE
;
MSG$ON$NEW$LINE:
PUSH D ;SAVE MESSAGE POINTER
CALL CRLF ;START NEW LINE
POP D ;RESTORE MESSAGE POINTER
PRINT$BUFFER:
MVI C,9 ;OUTPUT BUFFER TO CONSOLE
JMP BDOS
;
;
;ERROR ABORT ROUTINE
;
ERROR$ABORT:
PUSH D ;SAVE MESSAGE POINTER
LXI D,ERRMSG ;POINT "ERROR" MSG
CALL MSG$ON$NEW$LINE ;SEND IT OUT
POP D ;RESTORE MESSAGE POINTER
CALL PRINT$BUFFER ;SEND OUT ERR TYPE
LXI D,LAMESSAGE ;POINT "LOAD ADDR" MSG
CALL MSG$ON$NEW$LINE ;SEND IT OUT
CALL ABSOLUTE ;GET ABSOLUTE ADDR
CALL WORD$OUT ;SEND IT OUT
JMP EXIT ;BAIL OUT
;THIS ROUTINE PRINTS THE LOAD ADDRESS OF THE CURRENT
;HEX RECORD ON A NEW LINE FOLLOWED BY A ':' AND SPACE.
PRINT$LOAD$ADDR:
CALL CRLF
LHLD LOAD$ADDRESS
CALL WORD$OUT
MVI A,':'
CALL CHAR$TO$CONSOLE
MVI A,' '
JMP CHAR$TO$CONSOLE
;ROUTINE TO CLEAR THE COMFILE BUFFER.
CLEAR$COMBUFFER:
LXI H,COMFILE$BUFFER
LDA CURR$COM$BUF$END+1 ;PAGE NO. OF BUF END
MVI C,0 ;GET ZERO
CLOOP MOV M,C ;ZERO TO BUFFER
INX H ;BUMP POINTER
CMP H ;END OF BUFFER YET?
JNZ CLOOP ;LOOP TILL DONE
RET
;ROUTINE TO COMPUTE CURRENT ABSOLUTE LOAD ADDRESS
;AND RETURN IT IN <HL>
ABSOLUTE:
LHLD CURRENT$COM$BASE ;GET BASE OF COM BUFFER
MOV B,H ;MOVE IT TO <BC>
MOV C,L
LHLD COM$BUF$OFFSET ;GET THE CURRENT OFFSET
DAD B ;SUM IS THE ABSO ADDR
RET
; MESSAGES
ERRMSG:
DB 'ERROR: $'
DRMSG:
DB 'DISK READ$'
ILAMSG:
DB 'LOAD ADDRESS LESS THAN 100$'
DWMSG:
DB 'DISK WRITE$'
LAMESSAGE:
DB 'LOAD ADDRESS $'
EAMSG:
DB 'ERROR ADDRESS $'
IHDMSG:
DB 'INVALID HEX DIGIT$'
CSEMSG:
DB 'CHECKSUM ERROR $'
FAMSG:
DB 'FIRST ADDRESS $'
LSTADDRMSG:
DB 'LAST ADDRESS $'
BRMESSAGE:
DB 'BYTES READ $'
RWMSG:
DB 'RECORDS WRITTEN $'
COSMSG:
DB 'CANNOT OPEN SOURCE FILE$'
NMDSMSG:
DB 'DIRECTORY FULL$'
CCFMSG:
DB 'CANNOT CLOSE FILE$'
SIGNON$MSG:
DB 'HEXCOM VERS: ',VERS/100+'0'
DB '.',VERS/10 MOD 10 +'0'
DB VERS MOD 10 + '0',CR,LF,'$'
; DATA AREA
HEX$BUFFER$OFFSET DB 127
FIRST$ADDRESS DW 0
LAST$ADDRESS DW 0
BYTES$READ$COUNT DW 0
RECORDS$WRITTEN DB 0
LOAD$ADDRESS DW 100H
CURRENT$COM$BASE DW 100H
CHECKSUM DB 0
COM$BUF$OFFSET DW 0
CLEAR$FLAG DB 0 ;CLEAR-COM-BUF FLAG
; STORAGE AREA
STACK$SAVE DS 2
HEX$FCB DS 33
LOAD$COUNT DS 1
CURR$COM$BUF$END DS 2 ;COM BUFFER TOP
CURR$COM$BUF$LEN DS 2 ;COM BUFFER LENGTH
DS 32 ;STACK AREA
STACK EQU $
ORG ((HIGH $)+1)*256
HEX$BUFFER DS 128
COMFILE$BUFFER EQU $
END