include BDS.LIB .comment ~ /* CHARIO.C Character-oriented file I/O Assembly version, Greg Lee, July '84 Written 1980 by Scott W. Layson This code is in the public domain. These routines deal with reading and writing large blocks of characters, when they do not fit neatly in sectors. At the moment, only sequential output is supported; input is fully random. */ ~ ;TRUE equ -1 ;FALSE equ 0 NULL equ 0 .comment ~ /* i/o buffer */ struct iobuf { int fd; int isect; /* currently buffered sector */ int nextc; /* index of next char in buffer */ char buff [128]; }; ~ ;/* seek opcodes */ ABSOLUTE equ 0 RELATIVE equ 1 INPUT equ 0 OUTPUT equ 1 UPDATE equ 2 .comment ~ copen (buf, fname) /* open a file for char input */ struct iobuf *buf; char *fname; { ~ copen:: call carghak ; buf->fd = open (fname, INPUT); lxi h,INPUT push h lhld fname push h call open## pop d pop d xchg lhld buf mov m,e inx h mov m,d ; if (buf->fd == -1) return (-1); xchg ;(buf->fd) was still in DE inx h mov a,h ora l jz .errret ; jnz .o1 ; lxi h,-1 ; ret ; read (buf->fd, &buf->buff, 1); .o1: lxi h,1 push h lhld buf lxi d,6 dad d push h lhld buf mov e,m inx h mov d,m push d call read## pop d pop d pop d ; buf->isect = 0; .o2: lhld buf inx h inx h xra a mov m,a inx h mov m,a ; buf->nextc = 0; ; lhld buf ; lxi d,4 ; dad d ; xra a inx h mov m,a inx h mov m,a ; return (buf); ; } ; lhld buf ret .comment ~ ccreat (buf, fname) /* create a file for char output */ struct iobuf *buf; char *fname; { ~ ccreat:: call carghak ; buf->fd = creat (fname); lhld fname push h call creat## pop d xchg lhld buf mov m,e inx h mov m,d ; if (buf->fd == -1) return (-1); ; lhld buf ; mov e,m ; inx h ; mov d,m inx d mov a,d ora e jnz .o2 ; } ; .errret: lxi h,-1 ret .comment ~ cclose (buf) /* close the file assoc. with buf */ struct iobuf *buf; { close (buf->fd); } ~ cclose:: pop d pop h push h push d mov e,m inx h mov d,m push d call close## pop d ret .comment ~ cseek (buf, nbytes, code) /* seek to a character (input only!) */ struct iobuf *buf; unsigned nbytes, code; { int newsect; ~ cseek:: call carghak ; if (buf < 0) return (-1); ;????? ; if (code == RELATIVE) nbytes += buf->isect * 128 + buf->nextc; .s1: lhld code dcx h mov a,h ora l jnz .s2 lhld buf lxi d,4 dad d mov e,m inx h mov d,m ;DE = (buf->nextc) lhld buf inx h inx h inx h mov a,m rar dcx h mov a,m rar mov h,a mvi a,0 rar mov l,a ;HL = 128 * (buf->isect) dad d xchg lhld snbytes dad d shld snbytes ; newsect = nbytes / 128; .s2: lhld snbytes mov a,l ral mov a,h ral mov l,a mvi a,0 ral mov h,a shld newsect ; if (newsect != buf->isect ; push h ;HL = newsect xchg lhld buf inx h inx h mov a,m inx h mov h,m mov l,a ; pop d call eqwel jz .s4 ; && (seek (buf->fd, newsect, ABSOLUTE) == -1 lxi h,ABSOLUTE push h lhld newsect push h lhld buf mov e,m inx h mov d,m push d call seek## pop d pop d pop d inx h mov a,h ora l ; jz .s3 jz .errret ; || read (buf->fd, &buf->buff, 1) == -1)) return (-1); lxi h,1 push h lhld buf lxi d,6 dad d push h lhld buf mov e,m inx h mov d,m push d call read## pop d pop d pop d inx h mov a,h ora l jz .errret ; jnz .s4 ;.s3: lxi h,-1 ; jmp .s5 ; buf->nextc = nbytes % 128; .s4: lhld buf lxi d,4 dad d push h lhld snbytes mov a,l ani 7FH mov l,a mvi h,0 xchg pop h mov m,e inx h mov m,d ; buf->isect = newsect; lhld newsect xchg lhld buf inx h inx h mov m,e inx h mov m,d ; return (nbytes); ; } lhld snbytes ; jmp .s5 ;.s5: ret newsect: dw 0 .comment ~ cread (buf, dest, nbytes) /* read some bytes into dest */ struct iobuf *buf; char *dest; unsigned nbytes; { int navail, nsects, nleft, nread1, nread2; ~ cread:: call carghak ; if (buf < 0) return (-1); ;??? ; navail = umin (nbytes, 128 - buf->nextc); ;.r1: lhld buf lxi d,4 dad d mov e,m inx h mov d,m call cmd lxi h,128 dad d xchg lhld nbytes ; xchg call umin shld navail ; movmem (&buf->buff[buf->nextc], dest, navail); push h ;HL = navail, keep on stack for next few statements push h lhld dest push h lhld buf lxi d,4 dad d ;HL = buf->nextc mov e,m inx h mov d,m ;DE = (buf->nextc) inx h ;HL = buf->buff dad d push h call movmem## pop d pop d pop d ; nbytes -= navail; lhld nbytes pop d push d call cmd dad d shld nbytes ; buf->nextc += navail; lhld buf lxi d,4 dad d pop d push d call .pluseq+1 ; dest += navail; lhld dest pop d dad d shld dest ; nsects = nbytes / 128; lhld nbytes mov a,l ral mov a,h ral mov l,a mvi a,0 ral mov h,a shld nsects ; if (nsects) { ; lhld nsects mov a,h ora l jz .r4 ; nread1 = read (buf->fd, dest, nsects); push h ;HL = nsects lhld dest push h lhld buf mov e,m inx h mov d,m push d call read## pop d pop d pop d shld nread1 ; if (nread1 == -1) return (navail); inx h ;HL = ++nread1 mov a,h ora l jz .r9 ; jnz .r2 ; lhld navail ; ret ; buf->isect += nread1; .r2: dcx h xchg lhld buf inx h inx h xchg ; lhld nread1 push h call .pluseq ; if (nread1 < nsects) return (navail + nread1 * 128); ; lhld nread1 ; xchg pop d lhld nsects call albs jnc .r3 .r2a: lhld nread1 mov a,h rar mov a,l rar mov h,a mvi a,0 rar mov l,a jmp .r7a ; lhld navail ; dad d ; ret ; dest += nread1 * 128; .r3: lhld dest xchg lhld nread1 mov a,h rar mov a,l rar mov h,a mvi a,0 rar mov l,a dad d shld dest jmp .r5 ; } ; else nread1 = 0; .r4: lxi h,0 shld nread1 ; if (buf->nextc == 128) { .r5: lhld buf lxi d,4 dad d mov a,m cpi 128 ;+ jnz .r7 ;+ ; nread2 = read (buf->fd, &buf->buff, 1); lxi h,1 push h lhld buf lxi d,6 dad d push h lhld buf mov e,m inx h mov d,m push d call read## pop d pop d pop d shld nread2 ; if (nread2 == -1) return (navail); inx h ;HL = ++nread2 mov a,h ora l jz .r9 ; jnz .r6 ; lhld navail ; ret ; ++(buf->isect); .r6: lhld buf inx h inx h mov e,m inx h mov d,m inx d mov m,d dcx h mov m,e ; buf->nextc = 0; ; lhld buf ; lxi d,4 ; dad d inx h inx h xra a mov m,a inx h mov m,a ; if (nread2 < 1) return (navail + nread1 * 128); lhld nread2 lxi d,-1 dad d mov a,h ral ; jnc .r7 jc .r2a ; } .r7: ; nleft = nbytes % 128; lhld nbytes mov a,l ani 7FH mov l,a mvi h,0 shld nleft ; movmem (&buf->buff, dest, nleft); push h ;HL = nleft push h lhld dest push h lhld buf lxi d,6 dad d push h call movmem## pop d pop d pop d ; buf->nextc += nleft; lhld buf lxi d,4 dad d pop d call .pluseq+1 ; return (navail + nbytes); lhld nbytes .r7a: xchg ;+ lhld navail ;+ dad d ; } .r8: ret .r9: lhld navail ret .pluseq: xchg push h push d mov e,m inx h mov d,m pop h dad d xchg pop h mov m,e inx h mov m,d ret navail: dw 0 nsects: dw 0 nleft: dw 0 nread1: dw 0 nread2: dw 0 .comment ~ cwrite (buf, source, nbytes) /* write some bytes from source */ struct iobuf *buf; char *source; unsigned nbytes; { unsigned nleft, nfill, nsects; /* nleft not referenced */ ~ cwrite:: call carghak ; if (buf < 0) return (-1); ;?? ; if (buf->nextc) { .w1: lhld buf lxi d,4 dad d mov a,m inx h ora m jz .w2 ; nfill = umin (nbytes, 128 - buf->nextc); mov e,a mov d,m call cmd lxi h,128 dad d xchg lhld nbytes ; xchg ;+ call umin shld nfill ; movmem (source, &buf->buff[buf->nextc], nfill); push h ;HL = nfill, keep on stack push h lhld buf lxi d,4 dad d ;HL = buf->nextc mov e,m inx h mov d,m ;DE = (buf->nextc) inx h ;HL = buf->buff dad d push h lhld source push h call movmem## pop d pop d pop d ; buf->nextc += nfill; lhld buf lxi d,4 dad d pop d push d call .pluseq+1 ; nbytes -= nfill; lhld nbytes pop d push d call cmd dad d shld nbytes ; source += nfill; ; } lhld source pop d dad d shld source ; if (buf->nextc == 128) { .w2: lhld buf lxi d,4 dad d mov a,m cpi 128 jnz .w3 ; ++(buf->isect); ; lhld buf ; inx h ; inx h ; mov e,m ; inx h ; mov d,m ;HL = buf+4 from above dcx h mov d,m dcx h mov e,m ;HL = buf+2, DE = (isect) inx d ; mov m,d ; dcx h ; mov m,e mov m,e inx h mov m,d ;HL = buf+3 ; buf->nextc = 0; ; lhld buf ; lxi d,4 ; dad d inx h xra a ;HL = buf+4 = ->nextc mov m,a inx h mov m,a ;HL = buf+5 ; if (write (buf->fd, &buf->buff, 1) < 1) return (-1); ; } lxi d,1 push d ; lhld buf ; lxi d,6 ; dad d inx h push h ;HL = buf+6 = ->buff lhld buf mov e,m inx h mov d,m push d call write## pop d pop d pop d lxi d,-1 dad d mov a,h ral jc .errret ; jnc .w3 ; lxi h,-1 ; jmp .w5 ; nsects = nbytes / 128; .w3: lhld nbytes mov a,l ral mov a,h ral mov l,a mvi a,0 ral mov h,a shld nsects ; if (nsects && write (buf->fd, source, nsects) < nsects) ; return (-1); mov a,h ;HL = nsects ora l jz .w4 push h push h lhld source push h lhld buf mov e,m inx h mov d,m push d call write## pop d pop d pop d xchg pop h ; lhld nsects call albu jc .errret ; jnc .w4 ; lxi h,-1 ; jmp .w5 ; nbytes %= 128; .w4: lhld nbytes mov a,l ani 7FH mov l,a mvi h,0 shld nbytes ; movmem (source + nsects * 128, &buf->buff, nbytes); ; lhld nbytes push h push h lhld buf lxi d,6 dad d push h lhld nsects mov a,h rar mov a,l rar mov d,a mvi a,0 rar mov e,a lhld source dad d push h call movmem## pop d pop d pop d ; buf->nextc += nbytes; lhld buf lxi d,4 dad d pop d push d call .pluseq+1 ; return (nsects * 128 + nbytes); ; } ; lhld nbytes lhld nsects mov a,h rar mov a,l rar mov h,a mvi a,0 rar mov l,a pop d dad d .w5: ret nfill: dw 0 .comment ~ cflush (buf) /* flush an output buffer */ struct iobuf *buf; { ~ cflush:: call carghak ; if (buf->nextc && write (buf->fd, &buf->buff, 1) < 1) ; return (-1); lhld buf lxi d,4 dad d mov a,m inx h ora m jz .f1 lxi d,1 push d ; lhld buf ; lxi d,6 ; dad d inx h push h lhld buf mov e,m inx h mov d,m push d call write## pop d pop d pop d lxi d,-1 dad d mov a,h ral jc .errret ; jnc .f1 ; lxi h,-1 ; ret ; return (1); ; } .f1: lxi h,1 ret .comment ~ umin (a, b) /* unsigned min */ unsigned a, b; { return ((a < b) ? a : b); } ~ umin: ;HL = b ;DE = a call albu rnc ;ret HL = b if DE >= HL xchg ;else ret DE = a ret carghak: lxi d,cargs lxi h,4 dad sp push b mvi b,2*3 jmp arghk2 cargs: buf: dw 0 fname: snbytes: dest: source: dw 0 code: nbytes: dw 0 end