; ; ; "zload" ; ; (C) P.F.Ridler 1985 ; ; This program takes a .HEX file as input and produces from it a .COM file. ; Interblock spaces are zero filled. ; ; The command line for execution is ; ; loader [d:]name[.ext] [offset] ; ; The drive letter is optional, but if absent is taken to be the default ; drive. ; ; The filename extension is also optional and will always be taken to be .HEX ; ; The "offset" parameter is a hexadecimal number and is optional. If it ; is absent it will be taken to be 0000H, but if present will alter the ; load address of the code in the .COM file. ; If, for example, the origin of the code when it was compiled was 1000H ; the .COM file would start with F00H zeroes and then be followed by ; executable code. However, if the offset parameter were to be F100H, ; the code would start at (1000H+F100H)=100H and there would be no filler ; zeroes at the start of the .COM file. ; ; ; ; Free use is granted for private, non-commercial use only. ; Copies may be made for backup purposes, but the program may ; not be broadcast by communications networks. ; ; Enquiries should be addressed to: ; ; P.F.Ridler, ; 4, Lewisam Ave., ; Chisipite, ; ZIMBABWE. ; ; enclosing return postage. ; ; ; latest change ; ; 10 Jan 86 offset added ; 26 Dec 85 original ; ; wboot equ 0000H bdos equ 0005H dffcb equ 005CH dfdrv equ 0004H ; ; bel equ 7 lf equ 10 cr equ 13 ctrlz equ 26 esc equ 27 ; ; org 1000H ; ; jp load ; ; curpos ld a,esc ;this should position the cursor at call dspch ; row (H) and column (L) ld a,'Y' ;the top left corner of the screen is 0,0 call dspch ;the existing routine is for an H19 terminal ld a,32 add a,h call dspch ld a,32 add a,l call dspch ret ; ; clear ld a,esc ;this should clear the screen call dspch ld a,'E' call dspch ret ; ; load ld sp,stack call inishl ld de,ipfcb ;open source call opnfil inc c call z,error2 ;cannot find source file ld de,opfcb ;delete output call delfil call crtfil ;create output inc c call z,error3 ;cannot create output file call rdbyte ;discard ':' call dehex ;get count ld (count),a load1 ld a,(count) or a,a ;while (count>0) jp z,load4 jp m,load4 ld (chksum),a ; checksum=count call dehex ; get load address ld h,a call dehex ld l,a ld (ldaddr),hl ld a,(chksum) ; checksum=checksum + load address bytes add a,h add a,l ld (chksum),a call dehex ; discard mode ld hl,(ldaddr) ; if (load address0) dec a ld (count),a or a,a jp m,load32 call dehex ; write(dehex) call wrbyte ld b,a ld a,(chksum) add a,b ld (chksum),a inc de ; fas=fas+1 jr load3 load32 ld (fas),de call chcksum ; check sum call rdbyte ; discard call rdbyte call rdbyte ; discard ':' call dehex ; get count ld (count),a jp load1 load4 call wrlast ;write last record and close output call dspstat ;display stats jp wboot ;return to O/S ; ; gethex push af push hl push de ld hl,00 ld de,6DH gethex1 ld a,(de) inc de cp a,' ' jr z,gethex3 sub a,'0' cp a,10 jr c,gethex2 sub a,7 gethex2 add hl,hl add hl,hl add hl,hl add hl,hl add a,l ld l,a jr nc,gethex1 inc h jr gethex1 gethex3 ld (offset),hl pop de pop hl pop af ret ; ; comext db 'COM' hexext db 'HEX' ; inishl call clear ld h,4 ld l,25 call curpos call dspnxt db ' Zimsoft Hex loader',0 ld h,6 call curpos call dspnxt db '(C) P. F. Ridler 1985',0 ld h,12 ld l,0 call curpos ; call gethex ; ld hl,dffcb ;move file name from 5CH to input fcb ld de,ipfcb ld bc,12 ldir ld hl,hexext ;make input file type "HEX" ld de,ipfcb+9 ld bc,3 ldir ld hl,ipfcb+12 ;zero current extent ld (hl),0 ld hl,ipfcb+32 ; " " record ld (hl),0 ; ld hl,dffcb ;move filename to output fcb ld de,opfcb ld bc,12 ldir ld hl,comext ;make file type "COM" ld de,opfcb+9 ld bc,3 ldir ld hl,opfcb+12 ;zero current extent ld (hl),0 ld hl,opfcb+32 ; " " record ld (hl),0 ; ld hl,opbuff ;opbptr=opbuff ld (opbptr),hl ld hl,100H ;fas=100H ld (fas),hl ld hl,ipbmax ;force read of first record ld (ipbptr),hl ret ; ; ; takes two Hex digits in BC and returns their value in A ; ; dehex push bc call rdbyte ;get first digit sub a,'0' cp a,10 jr c,dehex1 sub a,7 dehex1 ld b,a and a,0F0H jp nz,dehex8 ;invalid Hex digit ld a,b add a,a add a,a add a,a add a,a ld b,a call rdbyte ;get second digit sub a,'0' cp a,10 jr c,dehex2 sub a,7 dehex2 ld c,a and a,0F0H jp nz,dehex8 ld a,c or a,b jr dehex9 dehex8 call dspnxt db cr,lf,'Invalid hex digit "',0 call dsp2hex call dspnxt db '" after load address ',0 ld hl,(ldaddr) call dsp4hex call press jp wboot dehex9 pop bc ret ; ; chcksum push af ;make sure the calculated checksum push bc ; is the same as that from the .HEX file. call dehex ;check_sum from file ld b,a ld a,(chksum) ;if (checksum<>calculated_sum) add a,b call nz,error7 ; error('checksum error') pop bc pop af ret ; ; rdbyte push hl ;read one byte from the input .HEX file push de ld hl,(ipbptr) ;if (ipbptr>=ipbmax) ld de,ipbmax call cphlde jp c,rdbyte1 ld hl,ipbuff ; taddr=ipbuff ld (taddr),hl ld hl,ipfcb ; fcb=ipfcb ld (fcb),hl call rdrcrd ; read_record or a,a call nz,error6 ; if (A<>0)read error ld hl,ipbuff ;ipbptr=0 rdbyte1 ld a,(hl) ;A=ipbuff[ipbptr] inc hl ;ipbptr=ipbptr+1 ld (ipbptr),hl pop de pop hl ret ; ; wrbyte push hl push de ld hl,(opbptr) ;if (opbptr>=opbmax) ld de,opbmax call cphlde jr c,wrbyte1 push af ; save A ld hl,opbuff ; taddr=opbuff ld (taddr),hl ld hl,opfcb ; fcb=opfcb ld (fcb),hl call wrrcrd ; write_record or a,a ; if (A<>0) call nz,error5 ; "write error" pop af ; restore A ld hl,opbuff ; opbptr=0 wrbyte1 ld (hl),a ;A=opbuff[opbptr] inc hl ;opbptr=opbprt+1 ld (opbptr),hl pop de pop hl ret ; ; wrlast push af push hl push de ld a,ctrlz ld de,opbmax-1 ld hl,(opbptr) call cphlde jr z,wrlst2 inc de wrlst1 call cphlde jr z,wrlst2 ld (hl),a inc hl jr wrlst1 wrlst2 ld hl,opbuff ld (taddr),hl ld hl,opfcb ld (fcb),hl call wrrcrd ld de,opfcb call clsfil pop de pop hl pop af ret ; ; opnfil push hl push de push bc ld c,15 call bdos pop bc pop de pop hl ret ; ; delfil push hl push de push bc ld c,19 call bdos pop bc pop de pop hl ret ; ; crtfil push hl push de push bc ld c,22 call bdos pop bc pop de pop hl ret ; ; clsfil push hl push de push bc ld c,16 call bdos pop bc pop de pop hl ret ; ; uctolc cp a,'A' jr c,uctolc9 cp a,'Z'+1 jr nc,uctolc9 add a,20H uctolc9 ret ; ; dspfnam ld a,(hl) ;get drive number inc hl cp a,0 ;if (drive_no==0) jr nz,dspfn1 ld a,(dfdrv) ; get default drive inc a dspfn1 add a,'a'-1 ;turn into letter call dspch ld a,':' call dspch ld b,8 dspfn2 ld a,(hl) inc hl cp a,' ' jr z,dspfn21 call uctolc call dspch dspfn21 djnz dspfn2 call dspnxt db '.com',0 ret ; ; dspstat call dspnxt db cr,lf,lf,lf,0 ld hl,(fas) ld de,0FFH or a,a sbc hl,de call dsp4hex call dspnxt db 'H bytes loaded into "',0 ld hl,opfcb call dspfnam call dspnxt db '".',0 ret ; ; cphlde push hl or a,a sbc hl,de pop hl ret ; ; setaddr push de ld de,(taddr) ld c,26 call bdos pop de ret ; ; rdrcrd push hl push de push bc call setaddr ld de,(fcb) ld c,20 call bdos pop bc pop de pop hl ret ; ; wrrcrd push hl push de push bc ld a,(ndots) inc a ld (ndots),a and a,03H jr nz,wrrcrd1 ld a,'.' call dspch xor a,a ld (ndots),a wrrcrd1 call setaddr ld de,(fcb) ld c,21 call bdos pop bc pop de pop hl ret ; ; dspmsg push af push de dspm1 ld a,(de) inc de or a,a jr z,dspm2 call dspch jr dspm1 dspm2 pop de pop af ret ; ; dspch push af push hl push de push bc ld e,a ld c,2 call bdos pop bc pop de pop hl pop af ret ; ; dspall push af cp a,' ' jr nc,dspall1 push af ld a,'^' call dspch pop af add a,40H dspall1 call dspch pop af ret ; ; getch push hl push de push bc ld c,1 call bdos pop bc pop de pop hl ret ; ; press call dspnxt db cr,lf,bel,'Press to continue',0 call getch ret ; ; dspnxt ex (sp),hl push af dspnx1 ld a,(hl) inc hl or a,a jr z,dspnx2 call dspch jr dspnx1 dspnx2 pop af ex (sp),hl ret ; ; dspblk call dspnxt db ' ',0 ret ; ; ; These are the error messages from DR "load" ; msg1 db cr,lf,'Invalid Hex character in input file',0 msg2 db cr,lf,'Cannot find source file',0 msg3 db cr,lf,'Cannot open output file',0 msg4 db cr,lf,'Load addresses not in increasing order',0 msg5 db cr,lf,'Output file write error',0 msg6 db cr,lf,'Input file read error',0 msg7 db cr,lf,'Check-sum error',0 ; ; error1 ld de,msg1 jp error0 error2 ld de,msg2 jp error0 error3 ld de,msg3 jp error0 error4 ld de,msg4 jp error0 error5 ld de,msg5 jp error0 error6 ld de,msg6 jp error0 error7 ld de,msg7 jp error0 error0 call dspmsg call press jp wboot ; ; crlf call dspnxt db cr,lf,0 ret ; ; dsp1hex push af and a,0FH cp a,10 jr c,dsp1h1 add a,7 dsp1h1 add a,30H call dspch pop af ret ; ; dsp2hex push af push af rrca rrca rrca rrca call dsp1hex pop af call dsp1hex pop af ret ; ; dsp4hex push af ld a,h call dsp2hex ld a,l call dsp2hex pop af ret ; ; msg01 db 'Error: $' msg02 db ', Load address $' msg03 db 'Disk read$' msg04 db 'Inverted load address$' msg05 db 'Disc write$' msg06 db 'Load address $' msg07 db 'Error address $' msg08 db 'Bytes read:$' msg09 db 'Invalid hex digit$' msg10 db 'Check sum error $' msg11 db 'First address $' msg12 db 'Last address $' msg13 db 'Bytes read $' msg14 db 'Records written $' msg15 db 'HEX',0 msg16 db 'Cannot open source$' msg17 db 'COM' msg18 db 'No more directory space$' msg19 db 'Cannot close file$' ; ; taddr ds 2 ;transfer address ; ipfcb ds 36 ;input fcb ipbptr ds 2 ; buffer pointer ipbuff ds 128 ; buffer ipbmax equ $ ;end of input buffer+1 ; opfcb ds 36 ;output fcb opbptr ds 2 ;output buffer pointer opbuff ds 128 ;output buffer opbmax equ $ ;end of output buffer+1 ; fcb ds 2 count ds 2 ;byte count for present hex record ldaddr ds 2 ;load address for present hex record offset dw 0 ;offset to add to load address fas ds 2 ;first available space in o/p file chksum ds 2 ndots db 0 ; stack equ $+100 ; ; end