; 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