; DTC LOADER ; 0100 = TBASE: EQU 100H 0100 ORG TBASE 0000 = BOOT: EQU 0 0005 = BDOS: EQU 5 0006 = MEMTOP: EQU BDOS+1 ;TOP OF AVAILABLE MEMORY ; BDOS FUNCTIONS 0009 = CONOUT: EQU 9 ;CONSOLE OUTPUT 000A = CONIN: EQU 10 ;CONSOLE INPUT 000F = OPENF: EQU 15 ;OPEN FILE 0010 = CLOSEF: EQU 16 ;CLOSE FILE 0011 = SEARCF: EQU 17 ;SEARCH FIRST 0014 = READF: EQU 20 ;READ SECTOR 0019 = INTDSK: EQU 25 ;INTERROGATE DISK ; 005C = TFCB: EQU 05CH ;DEFAULT FILE CONTROL BLOCK 005C = TET: EQU TFCB ;ENTRY TYPE 005D = TFN: EQU TET+1 ;FILE NAME 0065 = TFT: EQU TFN+8 ;FILE TYPE 0068 = TEX: EQU TFT+3 ;FILE EXTENT 006B = TRC: EQU TEX+3 ;RECORD COUNT 006C = TDM: EQU TRC+1 ;DISK ALLOCATION MAP 007C = TNR: EQU TDM+16 ;NEXT RECORD NUMBER ; 0080 = TBUFF: EQU 080H ;DEFAULT BUFFER ; 0080 = SECSIZ: EQU 128 ;SECTOR SIZE ; 000D = CR: EQU 0DH 000A = LF: EQU 0AH ; ; 0100 210000 LOAD: LXI H,0 ;SAVE CP/M STACK POINTER 0103 39 DAD SP 0104 22DE01 SHLD SAVESP 0107 31FC01 LXI SP,STACK ;SET STACK POINTER 010A CDFC01 CALL INIT ;INITIALIZE FILE PARAMETERS ; 010D 0E00 MVI C,0 ;CLEAR BUFFER COUNT 010F CD7C01 LOAD1: CALL GETCHR ;SCAN TO BEGIN OF LINE 0112 FE3A CPI ':' 0114 C20F01 JNZ LOAD1 0117 11E001 LXI D,COUNT ;GET LOAD COUNT 011A CDBA01 CALL HEXBYT 011D 3AE001 LDA COUNT ;DONE? 0120 B7 ORA A 0121 CA8D01 JZ EXIT 0124 11DA01 LXI D,LADDR ;GET LOAD ADDRESS 0127 CDAE01 CALL GETADR 012A E5 PUSH H ;ADD OFFSET 012B 2ADA01 LHLD LADDR 012E EB XCHG 012F 2ADC01 LHLD OFFSET 0132 19 DAD D 0133 11FC01 LXI D,LOW ;IS ADDRESS IN LOADER? 0136 CDD401 CALL COMPAR 0139 EB XCHG 013A F26601 JP LOAD2 013D 114801 LXI D,ERMES ;YES 0140 0E09 MVI C,CONOUT 0142 CD0500 CALL BDOS 0145 C38D01 JMP EXIT 0148 4C4F414420ERMES: DB 'LOAD ADDRESS WITHIN LOADER.',CR,LF,'$' ; 0166 E1 LOAD2: POP H ;RESTORE BUFFER POINTER 0167 CD7C01 CALL GETCHR ;SKIP SEPARATOR BYTE 016A CD7C01 CALL GETCHR 016D CDBA01 LOAD3: CALL HEXBYT ;LOAD DATA 0170 E5 PUSH H 0171 21E001 LXI H,COUNT ;DECREMENT COUNT 0174 35 DCR M 0175 E1 POP H 0176 C26D01 JNZ LOAD3 0179 C30F01 JMP LOAD1 ;END OF LINE ; ; ; ; GET CHARACTER FROM RECORD ; IN - HL=BUFFER POINTER ; C=BUFFER COUNT ; OUT-A=CHARACTER ; 017C AF GETCHR: XRA A ;BUFFER EMPTY? 017D B9 CMP C 017E C29F01 JNZ GETCH2 0181 0E14 MVI C,READF ;YES. GET NEXT RECORD 0183 C5 PUSH B 0184 D5 PUSH D 0185 CDA501 CALL FILEOP 0188 D1 POP D 0189 C1 POP B 018A CA9A01 JZ GETCH1 018D CDA301 EXIT: CALL CLOSE 0190 0E00 MVI C,0 ;RESTORE LOGGED DRIVE 0191 = DRIVE: EQU $-1 0192 CD9201 CALL $ 0193 = SELDSK: EQU $-2 0195 2ADE01 LHLD SAVESP ;RESTORE CP/M STACK POINTER 0198 F9 SPHL 0199 C9 RET ; 019A 218000 GETCH1: LXI H,TBUFF 019D 0E80 MVI C,SECSIZ 019F 7E GETCH2: MOV A,M 01A0 23 INX H 01A1 0D DCR C 01A2 C9 RET ; ; ; ; 01A3 0E10 CLOSE: MVI C,CLOSEF 01A5 115C00 FILEOP: LXI D,TFCB 01A8 CD0500 CALL BDOS 01AB FE00 CPI 0 01AD C9 RET ; GET ADDRESS ; IN - HL=4 DIGIT ASCII HEX ADDRESS ; DE=ADDRESS OF RESULT ; 01AE 13 GETADR: INX D ;POINT TO MOST SIGN. BYTE 01AF CDBA01 CALL HEXBYT 01B2 1B DCX D 01B3 1B DCX D 01B4 CDBA01 CALL HEXBYT 01B7 13 INX D 01B8 AF XRA A 01B9 C9 RET 01BA CDC901 HEXBYT: CALL ASCHEX 01BD 07 RLC 01BE 07 RLC 01BF 07 RLC 01C0 07 RLC 01C1 47 MOV B,A 01C2 CDC901 CALL ASCHEX 01C5 80 ADD B 01C6 12 STAX D 01C7 13 INX D 01C8 C9 RET 01C9 CD7C01 ASCHEX: CALL GETCHR 01CC D630 SUI '0' 01CE FE0A CPI 10 01D0 F8 RM 01D1 D607 SUI 7 01D3 C9 RET ; COMPARE HL & DE ; OUT - FLAGS ARE SET TO RESULT OF HL - DE ; 01D4 7C COMPAR: MOV A,H 01D5 BA CMP D 01D6 C0 RNZ 01D7 7D MOV A,L 01D8 BB CMP E 01D9 C9 RET ; ; ; VARIABLES 01DA 0000 LADDR: DW 0 ;LOAD ADDRESS 01DC 0000 OFFSET: DW 0 ;LOAD OFFSET 01DE 0000 SAVESP: DW 0 ;CP/M STACK POINTER 01E0 0000 COUNT: DW 0 ;LOAD COUNT OF LINE 01E2 DS 26 STACK: 01FC = LOW: EQU $ ;LOW LOAD ADDRESS ; ; 01FC 0E19 INIT: MVI C,INTDSK ;SAVE CURRENTLY LOGGED DISK 01FE CD0500 CALL BDOS 0201 329101 STA DRIVE 0204 2A0100 LHLD BOOT+1 ;GET SELECT DISK ADDRESS 0207 2E1B MVI L,3*9 0209 229301 SHLD SELDSK 020C 227602 SHLD INISEL 020F 210000 LXI H,0 ;CLEAR OFFSET 0212 22DC01 SHLD OFFSET 0215 0616 MVI B,22 ;SET MAX CHAR SCAN 0217 3A5D00 LDA TFN ;WAS FILE SPECIFIED? 021A FE20 CPI ' ' 021C C24002 JNZ INIT1 021F 3E14 MVI A,20 ;NO. SET MAX BUFFER LENGTH 0221 328000 STA TBUFF 0224 114303 INIT0: LXI D,FNMES ;OUTPUT FILENAME MESSAGE 0227 0E09 MVI C,CONOUT 0229 CD0500 CALL BDOS 022C 118000 LXI D,TBUFF ;INPUT FILE NAME 022F 0E0A MVI C,CONIN 0231 CD0500 CALL BDOS 0234 CD3703 CALL CRLF 0237 3A8100 LDA TBUFF+1 ;# CHARS IN BUFFER 023A FE00 CPI 0 023C CA2402 JZ INIT0 023F 47 MOV B,A ;B:=# CHARS IN BUFFER 0240 218100 INIT1: LXI H,TBUFF+1 0243 3A8300 LDA TBUFF+3 ;DRIVE SPECIFIED? 0246 FE3A CPI ':' 0248 C27C02 JNZ INITD3 024B 23 INX H 024C 7E MOV A,M 024D D641 SUI 'A' ;YES. LEGAL DRIVE # 024F FA5702 JM INITD1 0252 FE10 CPI 16 0254 FA7302 JM INITD2 0257 116202 INITD1: LXI D,DRVMES ;NO 025A 0E09 MVI C,CONOUT 025C CD0500 CALL BDOS 025F C38D01 JMP EXIT 0262 494E56414CDRVMES: DB 'INVALID DRIVE.',CR,LF,'$' 0273 C5 INITD2: PUSH B 0274 4F MOV C,A ;SELECT DRIVE 0275 CD7502 CALL $ 0276 = INISEL: EQU $-2 0278 C1 POP B 0279 218300 LXI H,TBUFF+3 INITD3: 027C 115C00 LXI D,TFCB 027F 23 INIT2: INX H 0280 13 INX D 0281 7E MOV A,M 0282 FE2E CPI '.' ;END OF NAME? 0284 CAA002 JZ INIT4 0287 FE20 CPI ' ' 0289 CABF02 JZ INIT7 028C FE0D CPI CR 028E CAD902 JZ INIT9 0291 FE60 CPI 060H ;NO. LOWER CASE? 0293 DA9802 JC INIT3 0296 D620 SUI 020H ;YES. CONVERT TO UPPER CASE 0298 12 INIT3: STAX D 0299 05 DCR B 029A C27F02 JNZ INIT2 029D C3D902 JMP INIT9 02A0 116400 INIT4: LXI D,TFT-1 ;GET FILE TYPE 02A3 23 INIT5: INX H 02A4 13 INX D 02A5 7E MOV A,M 02A6 FE20 CPI ' ' 02A8 CABF02 JZ INIT7 02AB FE0D CPI CR 02AD CAD902 JZ INIT9 02B0 FE60 CPI 060H 02B2 DAB702 JC INIT6 02B5 D620 SUI 020H 02B7 12 INIT6: STAX D 02B8 05 DCR B 02B9 C2A302 JNZ INIT5 02BC F2D902 JP INIT9 02BF 23 INIT7: INX H ;SCAN FOR OFFSET 02C0 7E MOV A,M 02C1 FE3D CPI '=' 02C3 CAD202 JZ INIT8 02C6 FE0D CPI CR 02C8 CAD902 JZ INIT9 02CB 05 DCR B 02CC C2BF02 JNZ INIT7 02CF C3D902 JMP INIT9 02D2 23 INIT8: INX H ;GET OFFSET 02D3 11DC01 LXI D,OFFSET 02D6 CDAE01 CALL GETADR INIT9: 02D9 3A6500 LDA TFT ;WAS FILE TYPE SPECIFIED? 02DC FE20 CPI ' ' 02DE C2F102 JNZ INIT11 02E1 215103 LXI H,HEXMES ;SET FILE TYPE TO HEX 02E4 116500 LXI D,TFT 02E7 0603 MVI B,3 02E9 7E INIT10: MOV A,M 02EA 12 STAX D 02EB 23 INX H 02EC 13 INX D 02ED 05 DCR B 02EE C2E902 JNZ INIT10 INIT11: 02F1 116800 LXI D,TEX ;CLEAR EXTENT AND 02F4 0604 MVI B,4 ; RECORD COUNT 02F6 AF XRA A 02F7 12 INIT12: STAX D 02F8 13 INX D 02F9 05 DCR B 02FA C2F702 JNZ INIT12 02FD 117C00 LXI D,TNR ;CLEAR NEXT RECORD NUMBER 0300 12 STAX D 0301 0E11 MVI C,SEARCF 0303 CDA501 CALL FILEOP ;LOOKUP HEX FILE 0306 FEFF CPI 0FFH 0308 C23103 JNZ INIT13 030B 111603 LXI D,EXIMES ;OUTPUT ERROR MESSAGE 030E 0E09 MVI C,CONOUT 0310 CD0500 CALL BDOS 0313 C38D01 JMP EXIT 0316 4845582046EXIMES: DB 'HEX FILE DOES NOT EXIST.',CR,LF,'$' INIT13: 0331 0E0F MVI C,OPENF ;OPEN HEX FILE 0333 CDA501 CALL FILEOP 0336 C9 RET ; ; 0337 114003 CRLF: LXI D,CRLFM 033A 0E09 MVI C,CONOUT 033C CD0500 CALL BDOS 033F C9 RET 0340 0D0A24 CRLFM: DB CR,LF,'$' 0343 46494C454EFNMES: DB 'FILENAME ... $' 0351 484558 HEXMES: DB 'HEX' 0354 END