Rev 679 | Blame | Compare with Previous | Last modification | View Log | Download
;; BD Software C Compiler v1.6; Standard Library Machine Language Functions (part C); Copyright (c) 1982, 1986 by BD Software, Inc.;; This file is in "CSM" format; to convert to CRL format,; use CASM.SUB in conjunction with CASM.COM, ASM.COM and CLOAD.COM;; Functions appearing in this file:;; setfcb open close creat unlink rename fabort; fcbaddr read write seek tell hseek htell; cfsize oflow errno [errmsg] execl;;INCLUDE "bds.lib"if 1==0;; Setfcb:; setfcb(fcbaddr, filename); char *filename;;; Parse a given filename onto a given FCB area. This function does NOT; recognize user number prefixes on filenames; that is a feature limited; to internal subroutines within the C low-level-file-I/O library and not; generally available to users.;FUNCTION "SETFCB"FUNCHEAD setfcbszcall arghakpush bclhld arg2 ;get pointer to name textigsp: ld a,(hl)inc hlcp ' '_1=$+1jp z,igspcp tab_2=$+1jp z,igspdec hlex de,hl ;set DE pointing to 1st non-space charlhld arg1 ;get --> fcb areacall setfcb ; do itld hl,0 ;all OK.pop bcretENDFUNC setfcbsz,2endif;; Open:; int open(filename,mode); char *filename;;; Open a file for read (mode == 0), write (mode == 1) or both (mode = 2),; and detect a user-number prefix. Returns a file descriptor.;if NEDOOS==1FUNCTION "OPEN"FUNCHEAD openszcall arghakxor acall fgfcb ;any fcb's free? ;return A=fd, DE=fd addrjr nc,open2 ;if not, errorld a,10 ;"no more file slots"jp erroropen2:push bcpush af ;fdpush de ;fd addrlhld arg1ex de,hlOS_OPENHANDLEpop hl ;fd addrld (hl),bpop af ;fdld l,ald h,0pop bcretENDFUNC opensz,0else ;CP/MFUNCTION "OPEN"FUNCHEAD openszcall arghakxor acall fgfcb ;any fcb's free?_1=$+1jp nc,open2 ;if not, errorld a,10 ;"no more file slots"jp erroropen2: sta tmpex de,hllhld arg1ex de,hlpush bccall setfcu ;parse name and set usenum;lda usrnum;call setusr ;set new user number;jr $;jr $ld c,openccall bdoscp errorv ;successful open?pop bcld a,11 ; set error code in case of error_2=$+1jp z,oerror ;if error, go abortlda tmpcall fgfd ;get HL pointing to fd table entrylda arg2or a ;open for read?ld d,3_3=$+1jp z,open4dec ald d,5_4=$+1jp z,open4 ;write?dec ald a,12 ;"bad mode" for open operation..._5=$+1jp nz,oerror ;...if not mode 2ld d,7 ;else must be mode 2.open4: lda usrnum ;get user number for the fileadd d ;add r/w bit codesld (hl),a ;and store in fd tableinc hl ;clear max sector number field of fd entryxor ald (hl),ainc hlld (hl),alda tmp ;get back fdld l,ald h,0;call rstusr ;reset user numberretoerror: ;call rstusr ;reset user number;jr $sta errnum ;store error code numberjp error ;and return general error conditionENDFUNC opensz,5endif;; Close:; close(fd);;; Close a file opened via "open" or "creat":;FUNCTION "CLOSE"FUNCHEAD closeszjp close ;jump to the close routine in C.CCCENDFUNC closesz,0;; Creat:; int creat(filename); char *filename;; Creates the named file, first deleting any old versions, and opens it; for both read and write. Returns a file descriptor.;if NEDOOSFUNCTION "CREAT"FUNCHEAD creatszcall arghakxor acall fgfcb ;any fcb's free? ;return A=fd, DE=fd addrjr nc,creat2 ;if not, errorld a,10 ;"no more file slots"jp errorcreat2:push bcpush af ;fdpush de ;fd addrlhld arg1ex de,hlOS_CREATEHANDLEpop hl ;fd addrld (hl),bpop af ;fdld l,ald h,0pop bcretENDFUNC creatsz,0elseFUNCTION "CREAT"EXTERNAL "UNLINK"EXTERNAL "OPEN"FUNCHEAD creatsz_1=$+1jp (2 +1)*3_unlink=$jp 0_open=$jp 0call arghaklhld arg1push bcpush hl_2=$+1call _unlink ;erase any old versions of filepop de;lda usrnum ;set to appropriate user area computed by "unlink";call setusr;jr $;;;from "open"xor acall fgfcb ;any fcb's free?jr nc,cropen2 ;if not, errorld a,10 ;"no more file slots"jp errorcropen2:sta tmpex de,hllhld arg1ex de,hlcall setfcu ;parse name and set usenum;lda usrnum;call setusr ;set new user number;;;ld c,creatc ;create the file;ld de,fcb ;assume fcb has been set by "unlink"call bdos;call rstusr ;restore previous user numbercp errorvpop bc_3=$+1jp nz,creat0 ;if no error, go openld a,13 ;"can't create file" error codesta errnumjp errorcreat0:lda tmp ;fdld l,ald h,0;ld hl,2 ;now open for read/write;push hl;lhld arg1;push hl_4=$+1ld de,_open;call _open;pop de;pop de;push bc;push hl;ld de,fcb ;assume fcb has been set by "unlink";push de;OS_FWRITE;pop de;OS_FWRITE;pop hl;pop bc ;keep bc!!!;jr $retENDFUNC creatsz,4endif;; Unlink:; unlink(filename); char *filename;;; Deletes the named file. User number prefixes are recognized:;;TODOFUNCTION "UNLINK"FUNCHEAD unlinkszcall ma1tohpush bcex de,hlld hl,fcbcall setfcu ;parse for fcb and compute user number;lda usrnum;call setusr ;set to correct user numberld c,delc ;deletecall bdos;call rstusr ;restore original user numberld hl,0pop bc ;restore BCcp errorv ;was BDOS able to find the file?ret nz ;if so, all done.ld a,11 ;set error code for "file not found"sta errnumdec hl ;return -1retENDFUNC unlinksz,0;; Rename:; int rename(old_name,new_name); char *old_name, *new_name;;; Renames the given file. User number prefixes are allowed, but only; the one on the first filename (if specified) effects the operation.;;TODOFUNCTION "RENAME"FUNCHEAD renameszcall arghakpush bc;renam:lhld arg1 ;get old nameex de,hl_1=$+1ld hl,wfcbcall setfcu ;compute user number and set fcblda usrnumcall setusr ;set to user number of first namelhld arg2ex de,hl_2=$+1ld hl,wfcb+16call setfcu ;parse second name, but ignore user number_3=$+1ld de,wfcbld c,renc ;perform rename operationcall bdos;call rstusr ;reset user numberld hl,0pop bc ;restore BCcp errorv ;was BDOS able to find the file?ret nz ;if so, all doneld a,11 ;set error code for "file not found"sta errnumdec hl ;return -1retwfcb: ds 53 ;space for working fcb'sENDFUNC renamesz,3;; Fabort:; fabort(fd);; Abort all operations on file fd. Has no effect under MP/(hl) II.;FUNCTION "FABORT"FUNCHEAD fabortszcall ma1tohcall fgfd_1=$+1jp nc,abrt2 ;legal fd?ld a,7sta errnum ;set "bad fd" error codejp errorabrt2:IF NOT MPM2ld (hl),0 ;clear entry in fd tableENDIFld hl,0retENDFUNC fabortsz,1;; Fcbaddr:; char *fcbaddr(fd); Returns a pointer to the internal file control block associated; with open file having descriptor fd.;FUNCTION "FCBADDR"FUNCHEAD fcbaddrszcall ma1tohcall fgfd ;is it an open file?_1=$+1jp nc,fcbad2 ;if so, go do itld a,7sta errnum ;"bad fd" error codejp errorfcbad2: call ma1tohcall fgfcb ;get fcb addr in HLretENDFUNC fcbaddrsz,1;; Write:; i = write(fd, buf, n);;; The random sector write function. Returns either the number; of sectors successfully written, or -1 on hard error. Any return; value other than n (the third arg) should be considered an error,; after which errno() can tell you the error condition and errmsg(errno()); can return a pointer to an appropriate error message text.;;NOW RETURNS NUMBER OF BYTES, NOT SECTORS!!!if NEDOOSFUNCTION "WRITE"FUNCHEAD writeszcall arghaklda arg1call fgfd ;compute fd address for fd in A: ;return hl=fd addrpush bcld b,(hl)ld de,(arg2)ld hl,(arg3)OS_WRITEHANDLEpop bcor aret zld hl,-1retENDFUNC writesz,0elseFUNCTION "WRITE"FUNCHEAD writeszcall arghaklda arg1call fgfdshld arg5 ;save pointer to fd table entryld d,(hl) ;save fd table entry in Dld a,7 ;prepare for possible "bad fd"or a_1=$+1jp c,werror;ld a,d;and 4ld a,9 ;prepare for possible "no write permission"or a_2=$+1jp z,werrorpush bc;ld a,d ;set user number;call setusrlda arg1 ;get fd;jr $;jr $;jr $call fgfcb ;compute fcb addressshld tmp2 ;save it awayld hl,0 ;clear success countshld tmp2alhld arg3add hl,hlld l,hld h,0shld arg3 ;size/128writ1: lhld arg3 ;done yet?ld a,hor l_3=$+1jp nz,writ2;take care of maximum sector count for cfsize:lhld tmp2 ;get fcb addressld de,33 ;point to random record fieldadd hl,deld e,(hl)inc hlld d,(hl) ;DE now holds random record number for next recpush de ;save itlhld arg5 ;get fd table pointerinc hl ;point to max valueld e,(hl) ;get in DEinc hlld d,(hl) ;now DE is old max value, HL points to end of entryex (sp),hl ;DE = old max, HL = current sector, STACK = tab ptrex de,hl ;HL = old max, DE = current sectorcall cmphd ;is old max less than current sector?pop hl ;get tab ptr in HL_4=$+1jp nc,writ1a ;if old max not < current sector, don't update maxld (hl),d ;else update max value with new sector numberdec hlld (hl),ewrit1a: lhld tmp2a ;if so, return countxor asrl hrr lrrald h,lld l,a ;count*128wrdone: ;call rstusr ;reset user numberpop bcretwrit2: lhld arg2 ;else get transfer addresspush hl ;save on stackex de,hl ;put in DEld c,sdma ;set DMA therecall bdospop hl ;get back transfer addressld de,128 ;bump by 128 bytes for next timeadd hl,deshld arg2 ;save -> to next 128 byteslhld tmp2 ;get addr of fcbex de,hl;ld c,writr ;write random sector;call bdos;jr $OS_FWRITElhld tmp2a ;get success count in HLor a ;error?_5=$+1jp z,writ3 ;if not, go do bookkeepingsta errnum ;else save error codeld hl,-1_6=$+1jp wrdonewrit3: inc hl ; else bump successful sector count,shld tmp2alhld arg3 ; debump countdown,dec hlshld arg3lhld tmp2 ; get address of fcbld bc,33 ; get address of random fieldadd hl,bcld c,(hl) ; bump 16-bit value at randominc hl ; recordld b,(hl) ; fieldinc bc ; ofld (hl),b ; fcbdec hl ; by oneld (hl),cld a,b ;overflow past 16-bit record count?or c_7=$+1jp nz,writ1 ; go for next sector if no overflowinc hl ;else set 3rd byte of random sector countinc hlld (hl),1ld a,14 ;set "past 65536th sector" error codesta errnum_8=$+1jp writ1a ;and don't read any more.werror: sta errnumjp errorENDFUNC writesz,8endif;; Seek:;; seek(fd, offset, origin); seeks to offset records if origin == 0,; to present position + offset if origin == 1,; or to end of file + offset if origin == 2.; (note that in the last case, the offset must be non-positive);; There are no errors returned by this function, aside from a; possible bad fd, because all the function does is fudge the; random-record field of an fcb...if the seek is out of bounds,; a subsequent direct file I/O operation (such as read or write); will draw the error.;FUNCTION "SEEK"EXTERNAL "CFSIZE"FUNCHEAD seeksz_1=$+1jp (1 +1)*3_cfsize=$jp 0call arghakpush bc ;save BClda arg1call fgfcb ;figure addr of fcbld a,7 ;prepare for possible "bad fd" error code_2=$+1jp nc,seek0sta errnum ;set the error codepop bc ;restore BCjp errorseek0: push hl ;save addr of fcbld de,33 ;get current position in DEadd hl,deld e,(hl)inc hlld d,(hl)lhld arg2 ;get offset in HLlda arg3 ;is origin == 0?or a_3=$+1jp z,rseek2 ;if so, HL holds new positiondec a ;no. is origin == 1?_4=$+1jp nz,rseek1add hl,de ;yes. add offset to current position_5=$+1jp rseek2 ;and result is in HLrseek1: ;else origin must be 2...lhld arg1 ;compute file sizepush de ;save current positionpush hl_6=$+1call _cfsizepop de ;pop argumentpop de ;pop useless current positionex de,hl ;place file size in DE; call fgfd; ld a,(hl); call setusr ;set the file's native user number;; pop de ;get fcb pointer back in DE; push de; ld c,cfsizc ;compute end of file position; call bdos; call rstusr ;reset user number; pop hl ;get fcb addr in HL again; push hl; call rseek3 ;get DE = positionlhld arg2 ;add offsetadd hl,de ;and HL holds new positionrseek2: ex (sp),hl ;get fcb, push new positionld de,33add hl,de ;HL points to random field of fcbpop de ;get new position in DEld (hl),e ;and put into fcbinc hlld (hl),dex de,hl ;and return the position valuepop bc ;pop saved BC off stackret;rseek3: ld de,33; add hl,de; ld e,(hl); inc hl; ld d,(hl); retENDFUNC seeksz,6;; Tell:;; i = tell(fd);;; Return random record position of file:;FUNCTION "TELL"FUNCHEAD tellszcall ma1toh ;get fd in Acall fgfcb_1=$+1jp nc,tell0ld a,7 ; "bad fd" errorsta errnumjp errortell0: ld de,33 ;go to random record fieldadd hl,deld a,(hl) ;get position in HLinc hlld h,(hl)ld l,aretENDFUNC tellsz,1;; Hseek:;; int hseek(fd, hoffset, loffset, origin);; Like seek(), except offset is specified as a 24-bit value, the high-order; 8 bits in hoffset and the low-order 16 bits in loffset.;; NOTE: Seeking relative to EOF (origin value of 2) should NOT be performed; if there has been any WRITING done to the END OF THE FILE since; the file was last opened.;FUNCTION "HSEEK"FUNCHEAD hseekszcall arghakpush bc ;save BClda arg1call fgfcb ;figure addr of fcbld a,7 ;prepare for possible "bad fd" error code_1=$+1jp nc,hseek0sta errnum ;set the error codepop bc ;restore BCjp errorhseek0: push hl ;save addr of fcb_2=$+1call hseek3 ; CDE = current positionlhld arg3 ; BHL = offset valuelda arg2ld b,alda arg4 ;is origin == 0?or a_3=$+1jp z,hseek2 ;if so, BHL holds new positiondec a ;no. is origin == 1?_4=$+1jp z,hseek1a ;if so, go add offset to current positionhseek1: lda arg1call fgfd ;origin == 2.;ld a,(hl);call setusr ;set the file's native user numberpop de ;get fcb pointer back in DEpush deld c,cfsizc ;compute end of file positioncall bdos;call rstusr ;reset user numberpop hl ;get fcb addr in HL againpush hl_5=$+1call hseek3 ;get CDE = EOF record numberlhld arg3 ;BHL contains offsethseek1a:add hl,de ;add CDE to BHLld a,badc cld b,a ;BHL contains new positionhseek2: ex (sp),hl ;get fcb, push low 16 bits of new positionld de,33add hl,de ;HL points to random field of fcbpop de ;get low 16 bits of new position in DEld (hl),e ;and put into fcbinc hlld (hl),dinc hlld (hl),c ;and set high order byteex de,hl ;and return the low 16 bits of new positionpop bc ;pop saved BC off stackrethseek3: ld de,33add hl,deld e,(hl)inc hlld d,(hl)inc hlld c,(hl)retENDFUNC hseeksz,5;; Htell:;; i = htell(fd);;; Return high-order byte of 24-bit random record position of file:;FUNCTION "HTELL"FUNCHEAD htellszcall ma1toh ;get fd in Acall fgfcb_1=$+1jp nc,htell0ld a,7 ; "bad fd" errorsta errnumjp errorhtell0: ld de,35 ;go to random record fieldadd hl,deld l,(hl) ;put value in L register,ld h,0 ;zero H register.retENDFUNC htellsz,1;; cfsize:; cfsize(fd);; Compute size of file, but leave random-record field at original value.;; NOTE: For files greater than 8 megabytes, do NOT use cfsize. Instead,; use hseek() to seek to end of file, then use htell() & tell() to obtain; high byte and low word, respectively, of the maximum record number.;FUNCTION "CFSIZE"FUNCHEAD cfsizesz;cfsizecall ma1tohcall fgfcb_1=$+1jp nc,cfsiz2ld a,7 ;"bad fd" errorsta errnumjp errorcfsiz2: push bc ;save BCpush hl ;save fcb addresscall ma3toh ;set user areacall fgfd ;get pointer to fd table entryld a,(hl)call setusrinc hlshld tmp2 ;save pointer to max sector valuepop de ;restore fcb address into DEld hl,33 ;get to random record fieldadd hl,depush hl ;save ptr to random record field for after BDOS callld a,(hl)inc hlld h,(hl)ld l,a ;HL = current settingpush hl ;save current value of random record fieldld c,cfsizc ;compute file sizecall bdospop bc ;pop old random record value into BCpop hl ;get pointer to random record fieldld e,(hl) ;get end-of-file sector number into DEinc hlld d,(hl)ld (hl),b ;restore original valuedec hlld (hl),clhld tmp2 ;get pointer to fd table max sector valuepush hl ;save ptr to max valueld a,(hl) ;get max sector value in HLinc hlld h,(hl)ld l,a ;now old max in HL, fsize value in DEcall cmphd ;is old max < current fsize?_2=$+1jp nc,cfsiz3 ;if not, just return old max as current maxex (sp),hl ;get back pointer to old max valueld (hl),e ;update with new fsize valueinc hlld (hl),dex de,hl ;put end-of-file sector number in HL for returncfsiz3: pop de ;clean up stack;call rstusr ;reset user areapop bcretENDFUNC cfsizesz,2;; Oflow:; i = oflow(fd);;; Returns true if the highest-order byte (the third byte) of the; sector count in the fcb for the given file is non-zero:;FUNCTION "OFLOW"FUNCHEAD oflowszcall ma1tohcall fgfcb_1=$+1jp nc,oflow0ld a,7 ;"bad fd" errorsta errnumjp error ;abort if file isn't validoflow0: ld de,35 ;look at high byte of sector positionadd hl,deld a,(hl)or a ;is it zero?ld hl,0ret z ;if so, no overflowinc hl ;else overflow.retENDFUNC oflowsz,1;; Errno:; int errno(); Returns last recorded file I/O error condition, set following the; last error encountered by the "read" and "write" functions.;FUNCTION "ERRNO"FUNCHEAD errnoszlda errnumld l,ald h,0retENDFUNC errnosz,0;; Errmsg:; errmsg(n); Prints out the BDS C file I/O error message having number n, as returned; by the "errno()" function.;if 1==1FUNCTION "ERRMSG"FUNCHEAD errmsgsznerrs: equ 14 ;highest legal error codecall ma1toh ;get the numbercp nerrs+1_1=$+1jp c,errms2ld hl,nerrs+1 ;get the error error messageerrms2: add hl,hl ;double to get table offset_2=$+1ld de,txtab ;get base of text pointer tableadd hl,de ;add to get appropriate pointerld a,(hl) ;return pointer in HLinc hlld h,(hl)ld l,aret_3=$txtab: dw err0_4=$dw err1_5=$dw err2_6=$dw err3_7=$dw err4_8=$dw err5_9=$dw err6_10=$dw err7_11=$dw err8_12=$dw err9_13=$dw err10_14=$dw err11_15=$dw err12_16=$dw err13_17=$dw err14_18=$dw errerrerr0: db 'No errors occurred yet',0err1: db 'Reading unwritten data',0err2: db 'Disk out of data space',0err3: db 'Can''t close current extent',0err4: db 'Seek to unwritten extent',0err5: db 'Can''t create new extent',0err6: db 'Seek past end of disk',0err7: db 'Bad file descriptor',0err8: db 'File not open for read',0err9: db 'File not open for write',0err10: db 'Too many files open',0err11: db 'File not found',0err12: db 'Bad mode to "open"',0err13: db 'Can''t create the file',0err14: db 'Seek past 65535th record',0errerr: db 'Errmsg: error number out of range',0ENDFUNC errmsgsz,18endif;; Execl modified 1/16/84 to work across user areas for programs > 16K long;FUNCTION "EXECL"FUNCHEAD execlszcall arghakpush bclhld arg1ex de,hlld hl,-60 ;compute &nfcb for use hereadd hl,sppush hl ; save for much later (will pop into BC)push hl ;make a few copies for local use belowpush hlcall setfcu ;set up COM file for execl-ing;lda usrnum;call setusr ;set destination user areapop hl ;get new fcb addrld bc,9 ;set extension to COMadd hl,bcld (hl),'C'inc hlld (hl),'O'inc hlld (hl),'M'pop de ;get new fcb addr againld c,openc ;open the file for readingcall bdoscp errorv_1=$+1jp nz,noerrrerr: pop hlpop bc;call rstusrjp errornoerrr: lhld arg2 ;any first parameter?ld a,hor l_2=$+1jp nz,excl0ld de,arg2 ;no...null out first default fcb slotpush deld hl,fcbcall setfcbpop hl_3=$+1jp excl0a ;and go null out 2nd fcb slotexcl0: ex de,hl ;yes.. place into first default fcb slotld hl,fcbcall setfcblhld arg3 ;any second parameter given?ld a,hor l_4=$+1jp nz,excl0ald hl,arg3excl0a: ex de,hl ;yes: stick it into second default fcb slotld hl,fcb+16call setfcbld de,tbuff+1 ;now construct command line:xor a ; zero tbuff+1 just in case thereld (de),a ; are no arg stringsld hl,8 ;get pointer to 1st arg string in HLadd hl,sp ; by offsetting 4 objects from the current SPld b,0 ;char count for com. line buf.excl1: push hl ;and construct command lineld a,(hl) ;get addr of next arg string pointerinc hlld h,(hl)ld l,a ;0000 indicates end of list.or h ;end of list?_5=$+1jp z,excl3ld a,' ' ;no. install next stringdec hlexcl2:_6=$+1call mpuc ;convert to upper case for command line bufferld (de),ainc deinc binc hlld a,(hl)or a ;end of string?_7=$+1jp nz,excl2pop hl ;yes.inc hl ;bump param pointerinc hl_8=$+1jp excl1 ;and go do next stringexcl3: pop hl ;clean up stackld a,b ;check for command buffer overflowcp 46h_9=$+1jp c,excl30 ;if no overflow, go load file_10=$+1ld de,errmsgld c,9 ;else comlain and abort...call bdos_11=$+1jp errerrmsg: db 7,'EXECL: Command line overflow',cr,lf,'$'excl30: ld hl,tbuff ;set length of command lineld (hl),b ;at location tbuffexcl3a:_12=$+1ld de,code0 ;copy loader down to end of tbuffld hl,tpa-55ld b,55 ;length of loaderexcl4: ld a,(de)ld (hl),ainc deinc hldec b_13=$+1jp nz,excl4pop bc ;get fcb pointer in BC;reset the SP:lhld base+6 ;get BDOS pointer in HLlda tpa ;look at first op byte of run-time pkgcp 31h ;begin with "lxi sp,"?_14=$+1jp nz,go0 ;if so, use the same value now...lhld tpa+1 ;else get special SP value_15=$+1jp go1go0: cp 21h ;begin with "ld hl" (the NOBOOT sequence?)_16=$+1jp nz,go1 ;if not, just use the BDOS addr as top of memoryld de,-2050 ;for NOBOOT, subtract 2100 from BDOS addradd hl,de ;and make that the new SPgo1: ld sp,hlld hl,basepush hl ;set base of ram as return addrlda curusr ;push current user number for bootcode to resetld e,apush dejp tpa-55 ;(go to `code0:')mpuc: cp 61h ;convert character in A to upper caseret ccp 7bhret ncsub 32ret;; This loader code is now: 55 bytes long.; Modified for v1.51 to reset user area only after entire load (11/83);code0: ld de,tpa ;destination address of new programcode1: push de ;push dma addrpush bc ;push fcb pointerld c,sdma ;set DMA address for new sectorcall bdospop de ;get pointer to working fcb in DEpush de ;and re-push itld c,reads ;read a sectorcall bdospop bc ;restore fcb pointer into BCpop de ;and dma address into DEor a ;end of file?jp z,tpa-8 ;if not, get next sector (goto `code2:')ld d,bld e,cld c,closeccall bdospop de ;restore current user number to Eld c,gsusercall bdos ;reset user numberld c,sdma ;reset DMA pointerld de,tbuffcall bdosjp tpa ;and go invoke the programcode2: ld hl,80h ;bump dma addressadd hl,deex de,hljp tpa-52 ;and go loop (at code1)ENDFUNC execlsz,16