;Program name: CFGSUBS.Z80 ;Author: Al Hawley ;Date 10/27/89 ;Previous Dates: 7 Dec 1988, 22 Sept 1988, 4 JUNE 1988 ;Program function: Subroutines used with ZCNFG ;standard definitions .xlist ;don't bother listing in PRN include sysdef .list ;symbols from other modules ext z3env,defdu ;from ZCNFG ext colcnt,rowcnt ext ma2hc ;from SYSLIB ext vpstr,stndout,stndend ;from VLIB ;symobls availale to other modules public b2bcd,clsfil,cin,cout,cpstr,cst,doftyp public getdr,gua,opnfil,range public rdfile,rdrec,setdma,stordt,strcpy public typlin,vcout,wrrec ;======================================================= ;install the default filetype located at FCB-3 in the ;fcb filetype field if it is currently filled with spaces. ;on entry, DE -> initialized FCB ; HL -> default file type ;on exit, DE is preserved. Others are munched. doftyp: push de ex de,hl ld bc,9 add hl,bc ld a,' ' cp a,(hl) ;first char of type blank? jr nz,fcbtyx ;return if not. User has supplied type ex de,hl ;de -> fcb+9, hl -> def type ld bc,3 ;3 char to move ldir ;move 'em fcbtyx: pop de ;fcb address ret ;======================================================= ; TEST FOR DE WITHIN RANGE ;Returns NC if DE is within the range. The range ;of values includes the endpoints. Returns CY set ;if DE > Max or DE < Min ;CALL WITH: ; DE = value to test ; HL = high end of range ; BC = low end of range ;RETURN WITH: ; DE and BC preserved ; HL destroyed ; Cy set = out of range, NC within RANGE: or a sbc hl,de ;test high limit ret c ;de higher than max push de ;save test value ex de,hl sbc hl,bc ;test lower limit pop de ret ;cy set = lower than min ;======================================================= ; B2BCD - Convert Binary Byte to BCD ;Call With A = binary value to convert ;Return with ; A = bcd tens,ones ; B = tens in high nibl ; C = hundreds ; Z = number <100, NZ = number >99 b2bcd: ld bc,0ffffh ;b,c =-1, rdy for first increment b2bcd1: inc c ;accumulate hundreds sub 100 jr nc,b2bcd1 add 100 ;too much - back up! b2bcd0: inc b ;accumulate 10s sub 10 jr nc,b2bcd0 add 10 ;too much - back up! rlc b ;shift into high nibl rlc b rlc b rlc b or b ;..and put into high nibl of A inc c dec c ;return nz if 100s present ret ;..and Z if not ;======================================================= ; SEND BYTES TO 3-CHAR FIELDS, LJUST. ; BYTE -> 2 ASCII CHAR, 1 POSITION SKIPPED. ; Typically used to fill in '__/__/__' ;CALL WITH: ; HL -> Source (bytes) ; DE -> Destination for ASCII ; B = number of bytes to convert ;RETURN WITH: ; HL -> next dest. & source ; DE is preserved STORDT: push de strdt0: push bc ;counter ld a,(hl) call ma2hc ;send Hex ASCII to dest. inc de ;skip a dest. position inc hl ;-> next source byte pop bc ;recover counter djnz strdt0 pop de ret ;=========================================================== ;CST, CIN, and COUT are replacements for the ;SYSLIB routines of the same name. Whereas SYSLIB ;uses BIOS calls for these functions, the replacements ;here use DOS function 6 calls for console status, ;input, and output. These routines take the place of ;SYSLIB routines with the same name if this module is ;linked ahead of SYSLIB. ;-------------------------- ; CST - console status using DOS function6 with ;Z flag inverted to agree with SYSLIB CST. cst: call cst6 ; get FN 6 console stat jr z,cstx ; invert the Z flag ld a,1 cstx: dec a ; a->0ff if z, a->0 if nz ret ; and flags are readjusted to match ;console status using DOS function 6 ;exit: Z = no character waiting ; NZ = Character waiting cst6: push de push bc push hl ld e,0feh ; console status call ld c,6 ; bdos function number call bdos and a ; anything there? pop hl pop bc pop de ret ;-------------------------- ; CIN - console input using DOS function 6 ;exit: A contains the character, and NZ ; if A=0 then there was no character ; and Z cin: push de push bc push hl ld e,0ffh ; get console input ld c,6 call bdos and a ; will be nz if present pop hl pop bc pop de ret ;-------------------------- VCOUT: cp 3 ;0,1, or 2? jr nc,cout ;use cout if not or a ;00? ret z ;don't even bother sending! dec a ;1? (^A) ? jp z,stndout ;yep, start standout mode & ret jp stndend ;else must be end of standout ;-------------------------- ; COUT - console output using DOS function 6 ;entry: A = char to be output, 0-FCH ;exit: char sent to console ; AF and 8080 registers preserved cout: push de push bc push hl push af call tabs ld e,a ld c,6 call nc,bdos pop af pop hl pop bc pop de ret ;=========================================================== ;tabs routine to be called from cout ; NOTE: this routine does not account for ; BS and 7fh characters tabs: ld hl,colcnt ;column counter (in ZCNFG) ld c,(hl) cp tab jr z,tabify cp cr jr nz,tabs01 ld c,0 ;CR resets column counter jr tabsx tabs01: cp lf jr nz,tabs02 inc hl inc (hl) ;increment line counter dec hl tabs02: cp spc ;ret cy set for cntl chars ccf ;NC = current char is string to copy ; DE->destination ; B = Max length of string ; RETURN WITH: ; A=delimiter ; HL->delimiter ; DE->next unwritten loc in dest. ; the delimiter is not copied. strcpy: ld a,(hl) cp '$' ;delimiter? ret z or a,a ;delimiter? ret z bit 7,a jr nz,strhbs ld (de),a ;transfer a byte inc hl inc de djnz strcpy ret strhbs: res 7,a ;reset high bit ld (de),a ;transfer last char inc de ;next dest ret ;ret hl->delimiting char ;================================================= ; PRINT NULL TERMINATED STRING typlin: ex de,hl call vpstr ex de,hl ret ;================================================= ; OPEN FILE ; Z SET IF FILE NOT FOUND ;on entry, A contains desired user # opnfil: call setusr ld a,15 call bdosin cp 255 jr resusr ;================================================= ; CLOSE FILE ;on entry, A contains desired user # clsfil: call setusr ld a,16 call bdosin cp 255 jr nz,resusr ld de,closer call typlin rst 0 closer: db 'CLOSE ERROR',0 ;================================================= ;set the user number to that passed in A ;IF IT IS A NUMBER <255 setusr: cp 0ffh ;is default requested? jp nz,sua ;jmp if user specified ;else fall through and set default user ;================================================= ;RESTORE THE DEFAULT USER NUMBER resusr: push af ld a,(defdu) call sua pop af ret ;================================================= ; READ ENTIRE FILE INTO DMA ADDRESS ;CALL WITH ; DE -> FCB ; HL = DMA address rdfile: ld bc,128 ;sector size rdf_lp: ex de,hl ;DE=dma, hl=fcb call setdma ex de,hl ;DE=fcb call rdrec ret c ;end of file add hl,bc jr rdf_lp ;================================================= ; READ NEXT RECORD rdrec: ld a,20 call bdosin or a ret z cp 2 ;check for eof ret c push af ;save error ld de,reader call typlin pop af or 30h ;make ascii call cout rst 0 reader: db 13,10,'READ ERROR = ',0 ;================================================= ; WRITE NEXT RECORD wrrec: ld a,21 call bdosin or a ret z cp 255 jp z,dirful push af ;save error ld de,writer call typlin pop af or 30h ;make ascii call cout rst 0 writer: db 13,10,'WRITE ERROR = ',0 ;================================================= ; SET DMA ADDRESS ; setdma: ld a,26 call bdosin ret ;================================================= ;set user area sua: push de and 1fh ;remove 3 msb to avoid ld e,a ;illegal user number ld a,32 call bdosin pop de ret ;================================================= ;get user area in A gua: push de ld e,-1 ld a,32 call bdosin pop de ret ;================================================= ;get current drive in A getdr: ld a,25 jr bdosin ;================================================= ; BDOS ENTRY ROUTINE ; bdosin: push hl push de push bc push ix push iy ld c,a ;set function call 5 ;bdos pop iy pop ix pop bc pop de pop hl ret ;================================================= ; DIRECTORY FULL ERROR ENTRY POINT ; dirful: ld de,direr call typlin rst 0 direr: db 'DIRECTORY FULL',0 ;================================================= end