; DTC LOADER
;
TBASE: EQU 100H
ORG TBASE
BOOT: EQU 0
BDOS: EQU 5
MEMTOP: EQU BDOS+1 ;TOP OF AVAILABLE MEMORY
; BDOS FUNCTIONS
CONOUT: EQU 9 ;CONSOLE OUTPUT
CONIN: EQU 10 ;CONSOLE INPUT
OPENF: EQU 15 ;OPEN FILE
CLOSEF: EQU 16 ;CLOSE FILE
SEARCF: EQU 17 ;SEARCH FIRST
READF: EQU 20 ;READ SECTOR
INTDSK: EQU 25 ;INTERROGATE DISK
;
TFCB: EQU 05CH ;DEFAULT FILE CONTROL BLOCK
TET: EQU TFCB ;ENTRY TYPE
TFN: EQU TET+1 ;FILE NAME
TFT: EQU TFN+8 ;FILE TYPE
TEX: EQU TFT+3 ;FILE EXTENT
TRC: EQU TEX+3 ;RECORD COUNT
TDM: EQU TRC+1 ;DISK ALLOCATION MAP
TNR: EQU TDM+16 ;NEXT RECORD NUMBER
;
TBUFF: EQU 080H ;DEFAULT BUFFER
;
SECSIZ: EQU 128 ;SECTOR SIZE
;
CR: EQU 0DH
LF: EQU 0AH
;
;
LOAD: LXI H,0 ;SAVE CP/M STACK POINTER
DAD SP
SHLD SAVESP
LXI SP,STACK ;SET STACK POINTER
CALL INIT ;INITIALIZE FILE PARAMETERS
;
MVI C,0 ;CLEAR BUFFER COUNT
LOAD1: CALL GETCHR ;SCAN TO BEGIN OF LINE
CPI ':'
JNZ LOAD1
LXI D,COUNT ;GET LOAD COUNT
CALL HEXBYT
LDA COUNT ;DONE?
ORA A
JZ EXIT
LXI D,LADDR ;GET LOAD ADDRESS
CALL GETADR
PUSH H ;ADD OFFSET
LHLD LADDR
XCHG
LHLD OFFSET
DAD D
LXI D,LOW ;IS ADDRESS IN LOADER?
CALL COMPAR
XCHG
JP LOAD2
LXI D,ERMES ;YES
MVI C,CONOUT
CALL BDOS
JMP EXIT
ERMES: DB 'LOAD ADDRESS WITHIN LOADER.',CR,LF,'$'
;
LOAD2: POP H ;RESTORE BUFFER POINTER
CALL GETCHR ;SKIP SEPARATOR BYTE
CALL GETCHR
LOAD3: CALL HEXBYT ;LOAD DATA
PUSH H
LXI H,COUNT ;DECREMENT COUNT
DCR M
POP H
JNZ LOAD3
JMP LOAD1 ;END OF LINE
;
;
;
; GET CHARACTER FROM RECORD
; IN - HL=BUFFER POINTER
; C=BUFFER COUNT
; OUT-A=CHARACTER
;
GETCHR: XRA A ;BUFFER EMPTY?
CMP C
JNZ GETCH2
MVI C,READF ;YES. GET NEXT RECORD
PUSH B
PUSH D
CALL FILEOP
POP D
POP B
JZ GETCH1
EXIT: CALL CLOSE
MVI C,0 ;RESTORE LOGGED DRIVE
DRIVE: EQU $-1
CALL $
SELDSK: EQU $-2
LHLD SAVESP ;RESTORE CP/M STACK POINTER
SPHL
RET
;
GETCH1: LXI H,TBUFF
MVI C,SECSIZ
GETCH2: MOV A,M
INX H
DCR C
RET
;
;
;
;
CLOSE: MVI C,CLOSEF
FILEOP: LXI D,TFCB
CALL BDOS
CPI 0
RET
; GET ADDRESS
; IN - HL=4 DIGIT ASCII HEX ADDRESS
; DE=ADDRESS OF RESULT
;
GETADR: INX D ;POINT TO MOST SIGN. BYTE
CALL HEXBYT
DCX D
DCX D
CALL HEXBYT
INX D
XRA A
RET
HEXBYT: CALL ASCHEX
RLC
RLC
RLC
RLC
MOV B,A
CALL ASCHEX
ADD B
STAX D
INX D
RET
ASCHEX: CALL GETCHR
SUI '0'
CPI 10
RM
SUI 7
RET
; COMPARE HL & DE
; OUT - FLAGS ARE SET TO RESULT OF HL - DE
;
COMPAR: MOV A,H
CMP D
RNZ
MOV A,L
CMP E
RET
;
;
; VARIABLES
LADDR: DW 0 ;LOAD ADDRESS
OFFSET: DW 0 ;LOAD OFFSET
SAVESP: DW 0 ;CP/M STACK POINTER
COUNT: DW 0 ;LOAD COUNT OF LINE
DS 26
STACK:
LOW: EQU $ ;LOW LOAD ADDRESS
;
;
INIT: MVI C,INTDSK ;SAVE CURRENTLY LOGGED DISK
CALL BDOS
STA DRIVE
LHLD BOOT+1 ;GET SELECT DISK ADDRESS
MVI L,3*9
SHLD SELDSK
SHLD INISEL
LXI H,0 ;CLEAR OFFSET
SHLD OFFSET
MVI B,22 ;SET MAX CHAR SCAN
LDA TFN ;WAS FILE SPECIFIED?
CPI ' '
JNZ INIT1
MVI A,20 ;NO. SET MAX BUFFER LENGTH
STA TBUFF
INIT0: LXI D,FNMES ;OUTPUT FILENAME MESSAGE
MVI C,CONOUT
CALL BDOS
LXI D,TBUFF ;INPUT FILE NAME
MVI C,CONIN
CALL BDOS
CALL CRLF
LDA TBUFF+1 ;# CHARS IN BUFFER
CPI 0
JZ INIT0
MOV B,A ;B:=# CHARS IN BUFFER
INIT1: LXI H,TBUFF+1
LDA TBUFF+3 ;DRIVE SPECIFIED?
CPI ':'
JNZ INITD3
INX H
MOV A,M
SUI 'A' ;YES. LEGAL DRIVE #
JM INITD1
CPI 16
JM INITD2
INITD1: LXI D,DRVMES ;NO
MVI C,CONOUT
CALL BDOS
JMP EXIT
DRVMES: DB 'INVALID DRIVE.',CR,LF,'$'
INITD2: PUSH B
MOV C,A ;SELECT DRIVE
CALL $
INISEL: EQU $-2
POP B
LXI H,TBUFF+3
INITD3:
LXI D,TFCB
INIT2: INX H
INX D
MOV A,M
CPI '.' ;END OF NAME?
JZ INIT4
CPI ' '
JZ INIT7
CPI CR
JZ INIT9
CPI 060H ;NO. LOWER CASE?
JC INIT3
SUI 020H ;YES. CONVERT TO UPPER CASE
INIT3: STAX D
DCR B
JNZ INIT2
JMP INIT9
INIT4: LXI D,TFT-1 ;GET FILE TYPE
INIT5: INX H
INX D
MOV A,M
CPI ' '
JZ INIT7
CPI CR
JZ INIT9
CPI 060H
JC INIT6
SUI 020H
INIT6: STAX D
DCR B
JNZ INIT5
JP INIT9
INIT7: INX H ;SCAN FOR OFFSET
MOV A,M
CPI '='
JZ INIT8
CPI CR
JZ INIT9
DCR B
JNZ INIT7
JMP INIT9
INIT8: INX H ;GET OFFSET
LXI D,OFFSET
CALL GETADR
INIT9:
LDA TFT ;WAS FILE TYPE SPECIFIED?
CPI ' '
JNZ INIT11
LXI H,HEXMES ;SET FILE TYPE TO HEX
LXI D,TFT
MVI B,3
INIT10: MOV A,M
STAX D
INX H
INX D
DCR B
JNZ INIT10
INIT11:
LXI D,TEX ;CLEAR EXTENT AND
MVI B,4 ; RECORD COUNT
XRA A
INIT12: STAX D
INX D
DCR B
JNZ INIT12
LXI D,TNR ;CLEAR NEXT RECORD NUMBER
STAX D
MVI C,SEARCF
CALL FILEOP ;LOOKUP HEX FILE
CPI 0FFH
JNZ INIT13
LXI D,EXIMES ;OUTPUT ERROR MESSAGE
MVI C,CONOUT
CALL BDOS
JMP EXIT
EXIMES: DB 'HEX FILE DOES NOT EXIST.',CR,LF,'$'
INIT13:
MVI C,OPENF ;OPEN HEX FILE
CALL FILEOP
RET
;
;
CRLF: LXI D,CRLFM
MVI C,CONOUT
CALL BDOS
RET
CRLFM: DB CR,LF,'$'
FNMES: DB 'FILENAME ... $'
HEXMES: DB 'HEX'
END