home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
BDSC
/
BDSC-1
/
DEFF2A.CQM
/
DEFF2A.CSM
Wrap
Text File
|
2000-06-30
|
11KB
|
672 lines
;
; BD Software C Standard Library Machine Language Functions
; Written by Leor Zolman
; v1.46, 3/15/82
;
; This file is in "CSM" format; to convert to CRL format,
; use CASM.SUB in conjunction with CASM.COM, ASM.COM and DDT.COM.
;
; Functions appearing in this file:
;
; rread rwrite rtell rseek rsrec rcfsiz
; setjmp longjmp
; setplot clrplot line plot txtplot
; index getline
;
;
;
; The random-record file I/O function contained here are NOT documented
; in the User's Guide, because they are non-portable to pre-2.0 CP/M
; Systems.
;
maclib bds
;
; Here are the new random-access file I/O routines
; for use with CP/M version 2.x ONLY...these functions
; will NOT work under pre-2.x CP/M's.
;
; The new functions are: rread, rwrite, rtell, rseek,
; rsrec, rcfsiz
;
;
; Rread:
;
; Read a number of sectors randomly.
; Usage:
;
; i = rread(fd, buf, n);
;
; The return value is either the number of sectors successfully
; read, 0 for EOF, or 1000 + (BDOS ERROR CODE)
;
; The Random Record Field is incremented following each successful
; sector is read, just as if the normal (sequentail) read function
; were being used. Rseek must be used to go back to a previous
; sector.
;
FUNCTION rread
call arghak
lda arg1
call fgfd
jc error
mov a,m
ani 2
jz error
push b
lda arg1
call fgfcb
shld tmp2
lxi h,0
shld tmp2a
r2: lhld arg3
mov a,h
ora l
lhld tmp2a
jnz r2a
pop b
ret
r2a: lhld arg2
xchg
mvi c,sdma
call bdos
lhld tmp2
xchg
mvi c,readr ;code for BDOS random read
push d ;save de so we can fudge nr field if
call bdos ;we stop reading on extent boundary...
pop d ; CP/M is a pain.
ora a
jz r4 ;go to r4 if no problem
cpi 1
jz r2b ;EOF?
mov c,a ;put return error code in BC
mvi b,0
lxi h,1000 ;add to 1000
dad b
pop b
ret
r2b: lxi h,32 ;yes. are we on extent boundary?
dad d
mov a,m
cpi 80h
jnz r3
mvi m,0 ;yes. reset nr to 0...CP/M leaves it at 80!
r3: lhld tmp2a ;(note: the above "bug" in CP/M was supposedly fixed
pop b ; for 2.x, but one can never be sure...)
ret
r4: lhld arg3
dcx h
shld arg3
lhld arg2
lxi d,128
dad d
shld arg2
lhld tmp2a
inx h
shld tmp2a
lhld tmp2 ;get address of fcb
lxi b,33 ;get addr of random record field
dad b
mov c,m ;bump
inx h ; value
mov b,m ; of
inx b ; random
mov m,b ; field
dcx h ; by one
mov m,c
jmp r2
ENDFUNC
;
; Rwrite:
;
; The random "write" routine, which always copies the sector
; to be written down to tbuff before writing. Returns
; the # of sectors successfully written, or -1 on hard error.
; (the "1000 + error code" business is not used for rwrite)
;
FUNCTION rwrite
call arghak
lda arg1
call fgfd
jc error
mov a,m
ani 4
jz error
push b
lda arg1
call fgfcb
shld tmp2
lxi h,0
shld tmp2a
lxi d,tbuff ;80 for normal CP/M, else 4280
mvi c,sdma
call bdos
nwr2: lhld arg3 ;done yet?
mov a,h
ora l
lhld tmp2a ;if so, return count
jnz nwr2a
pop b
ret
nwr2a: lhld arg2 ;else copy next 128 bytes down to tbuff
lxi d,tbuff ;80 for normal CP/M, else 4280
mvi b,128
nwr3: mov a,m
stax d
inx h
inx d
dcr b
jnz nwr3
shld arg2 ;save -> to next 128 bytes
lhld tmp2 ;get addr of fcb
xchg
mvi c,writr ;go write randomly
call bdos
ora a ;error?
lhld tmp2a ;if so, return # of successfully written
pop b ; sectors.
rnz
push b
inx h ; else bump successful sector count,
shld tmp2a
lhld arg3 ; debump countdown,
dcx h
shld arg3
lhld tmp2 ; get address of fcb
lxi b,33 ; get address of random field
dad b
mov c,m ; bump 16-bit value at random
inx h ; record
mov b,m ; field
inx b ; of
mov m,b ; fcb
dcx h ; by one
mov m,c
jmp nwr2 ; and go try next sector
ENDFUNC
;
; rseek:
;
; rseek(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)
;
FUNCTION rseek
call arghak
lda arg1
call fgfcb
jc error
push h
call rtell2
lhld arg2
lda arg3 ;is origin == 0?
ora a
jz rseek2 ;if so, HL holds new position
dcr a ;no. is origin == 1?
jnz rseek1
dad d ;yes. add offset to current position
jmp rseek2 ;and result is in HL
rseek1: pop d ;else origin must be 2...
push d
push b
mvi c,cfsizc ;compute end of file position
call bdos
pop b
pop h ;get back fcb
push h
call rtell2 ;get DE = position
lhld arg2 ;add offset
dad d ;and HL holds new position
rseek2: xthl ;get fcb, push new position
lxi d,33
dad d ;HL points to random field of fcb
pop d ;get new position in DE
mov m,e ;and put into fcb
inx h
mov m,d
xchg ;and return the position value
ret
rtell2: lxi d,33
dad d
mov e,m
inx h
mov d,m
ret
ENDFUNC
;
; Rtell:
;
; Return random record position of file:
;
FUNCTION rtell
call arghak
lda arg1
call fgfcb
jc error
lxi d,33 ;go to random record field
dad d
mov e,m ;get value into DE
inx h
mov d,m
xchg ;put into HL
ret
ENDFUNC
;
; Rsrec:
;
; Set random field from serial access mode:
;
FUNCTION rsrec
call arghak
lda arg1
call fgfcb
jc error
push h
xchg
push b
mvi c,srrecc
call bdos
pop b
pop h
lxi d,33
dad d
mov a,m
inx h
mov h,m
mov l,a
ret
ENDFUNC
;
; Rcfsiz:
;
; set random record field to end-of-file:
;
FUNCTION rcfsiz
call arghak
lda arg1
call fgfcb
jc error
push h
xchg
push b
mvi c,cfsizc
call bdos
pop b
pop h
lxi d,33
dad d
mov a,m
inx h
mov h,m
mov l,a
ret
ENDFUNC
FUNCTION setjmp
call ma1toh
mov m,c ;save BC
inx h
mov m,b
inx h
xchg
lxi h,0
dad sp
xchg
mov m,e ;save SP
inx h
mov m,d
inx h
pop d ;save return address
push d
mov m,e
inx h
mov m,d
lxi h,0 ;and return 0
ret
ENDFUNC
FUNCTION longjmp
call ma1toh ;get buffer address
mov c,m ;restore BC
inx h
mov b,m
inx h
mov e,m ;restore SP...first put it in DE
inx h
mov d,m
inx h
shld temp ;save pointer to return address
call ma2toh ;get return value
xchg ;put return val in DE, old SP in HL
sphl ;restore SP with old value
pop h ;pop retur address off stack
lhld temp ;get back ptr to return address
mov a,m
inx h
mov h,m
mov l,a ;HL holds return address
xchg ;put ret addr in DE, get return value in HL
push d ;push return address on stack
ret ;and return...
temp: ds 2
ENDFUNC
FUNCTION setplot
call arghak
push b
lhld arg1 ;get base address
shld pbase ; initialize
lhld arg3 ;get y size
shld ysize ; initialize
xchg ;leave it in DE
lhld arg2 ;get x size
shld xsize ; initialize
call usmul ;figure out screen size
shld psize ; initialize
pop b
ret
ENDFUNC
FUNCTION clrplot
lhld psize ;put screen size
xchg ; in DE
lhld pbase ;get screen base in HL
clr2: mvi m,' ' ;and
inx h ; clear
dcx d ; each
mov a,d ; location
ora e ; (all DE of 'em)
jnz clr2
ret
ENDFUNC
FUNCTION line
call arghak ;get args
push b
lda arg2 ;put one set of endpoint data in DE in
mov c,a ;format: D = x = arg2, E = y = arg3
lda arg3
mov b,a
mov d,b
mov e,c
call put ; put up one endpoint at BC
lda arg4 ;put other endpoint data in HL
mov c,a
lda arg5
mov b,a
call put ;(but first put up the point from BC)
mov h,b
mov l,c
call liner ;now connect them...
pop b
ret ;all done.
liner: mov a,d
sub h
call abs
cpi 2
jnc line2 ;are points far enough apart
;in both dimensions to warrant
mov a,e ;drawing a line?
sub l
call abs
cpi 2
jnc line2
ret ;if not, return.
line2: call midp ;find midpoint
call put ;put it up
push d ;set up recursive calls
mov d,b
mov e,c
call liner
xthl
call liner
xchg
pop h
ret ;and we are done!
midp: push h
push d
mov a,h
sub d
ani 1
jz mid3
mov a,h
cmp d
jc mid2a
inr d
jmp mid3
mid2a: dcr h
mid3: mov a,l
sub e
ani 1
jz mid4
mov a,l
cmp e
jc mid3a
inr e
jmp mid4
mid3a: dcr l
mid4: mov a,h
add d
ora a
rrc
mov b,a
mov a,l
add e
ora a
rrc
mov c,a
pop d
pop h
ret
put: push h
push d
mov a,b
lhld ysize
xchg
lhld pbase
inr a
put1: dcr a
jz put2
dad d
jmp put1
put2: mov e,c
mvi d,0
dad d
lda arg1
mov m,a
pop d
pop h
ret
abs: ora a
rp
cma
inr a
ret
ENDFUNC
FUNCTION plot
call arghak
lda arg1
lhld ysize
xchg
lhld pbase
inr a
plot1: dcr a
jz plotc
dad d
jmp plot1
plotc: lda arg2
mov e,a
mvi d,0
dad d
lda arg3
mov m,a
ret
ENDFUNC
FUNCTION txtplot
call arghak
push b
lhld arg2
xchg
lhld ysize
call usmul
xchg
lhld arg3
dad d
xchg
lhld pbase
dad d
xchg
lhld arg1
mvi b,0
lda arg4
ora a
jz txt2
mvi b,80h
txt2: mov a,m
ora a
jnz txt3
pop b
ret
txt3: ora b
stax d
inx h
inx d
jmp txt2
ENDFUNC
;
; Index(str,substr)
; char *str, *substr;
;
; Returns index of substr in str, or -1 if not found.
;
FUNCTION index
call arghak
lhld arg1
xchg ;main str ptr in DE
lhld arg2 ;substr ptr in HL
dcx d
index1: inx d
ldax d ;end of str?
ora a
jnz index2
lxi h,-1 ;yes. not found.
ret
index2: cmp m ;quick check for dissimilarity
jnz index1 ;loop if not same right here
push d ;else do long compare
push h
index3: inx h
inx d
mov a,m ;end of substr?
ora a
jnz index4 ;if not, go on testing
pop d ;else matches
pop d ;get starting address of substr in DE
lhld arg1 ;subtract beginning of str
call cmh
dad d ;and return the result
ret
index4: ldax d ;current char match?
cmp m
jz index3 ;if so, keep testing
pop h ;else go on to next char in str
pop d
jmp index1
ENDFUNC
;
; Getline(str,lim)
; char *str;
;
; Gets a line of text from the console, up to 'lim' characters.
;
FUNCTION getline
push b
call ma3toh ;get max no. of chars
mov c,a ;save in C
call ma2toh ;get destination address
push h
push h
lxi h,-150 ;use space below stack for reading line
dad sp
push h ;save buffer address
mov m,c ;Set max # of characters
mvi c,getlin
xchg ;put buffer addr in DE
call bdos ;get the input line
mvi c,conout
mvi e,lf ;put out a LF
call bdos
pop h ;get back buffer address
inx h ;point to returned char count
mov b,m ;set B equal to char count
inx h ;HL points to first char of line
pop d ;DE points to start destination area
copyl: mov a,b ;copy line to start of buffer
ora a
jz gets2
mov a,m
stax d
inx h
inx d
dcr b
jmp copyl
gets2: xra a ;store terminating null
stax d
pop h ;return buffer address in HL
pop b
ret
ENDFUNC