h44555
s 00560/00000/00000
d D 1.1 83/01/20 11:22:03 tes 1 0
c date and time created 83/01/20 11:22:03 by tes
e
u
tes
mjb
U
t
T
I 1
;
;       pl/i overlay routines
;       modified 4/19/81 to close files after read for MP/M
;
;       there are 2 entry points to these routines.
;
;               ?ovla0 - for implicit call (generated by link)
;               ?ovlay - for explicit call from pl/i program
;
        title   'pl/i overlay routines'
        name    'PL1OVL'
;
;
; for debugging
;
;        public  search, loadov, chksiz, update, insert, rdov
;        public  ovtab, ovfcb, curtab, nameptr, novltmp, loadadr, endadr
;
;;
;
        public  ?ovlay, ?ovla0
	public	ovlay
;
?boot	equ	0
?bdos	equ	5
?dbuff	equ	80H
true    equ     1
false   equ     0
cr      equ     0dh
lf      equ     0ah
sector  equ     80h
loadb   equ     8       ;load address is byte 8 of ovtab entry
endb    equ     10      ;end address is byte 10 of ovtab entry
hloadb  equ     7       ;load address is byte 7 of header record
hsizeb  equ     1       ;size is byte 1 of header record
ovnaml  equ     8       ;8 character overlay names
oventl  equ     12      ;12 bytes per overlay table entry
maxnst  equ     5       ;maximum depth of overlay nesting
                        ;used to allocate ovtab
msgsiz  equ     8       ;bytes per error message
        page
?ovla0:
;
;       called with:
;               bc = pointer to ascii overlay name
;               hl = pointer to pl/i parameter address list (if there is one)
;
        push    h       ;save first parameter      
	push    d       ;save second parameter 
        lda     ?dfdrv
        sta     ovfcb   ;set drive byte to default drive
        mov     l,c
        mov     h,b
        shld    nameptr ;save pointer to overlay name
        lxi     h,preset;preset by previous explicit call flag
        mov     a,m
        rar
        mvi     m,0     ;reset flag
        jc      noload  ;if preset, don't load, just go to load address
        call    search  ;see of overlay is in overlay table
        rar
        cnc     loadov  ;if it's not in memory, load it
noload:
        lhld    loadadr ;entry point to overlay
	pop     d       ;get second parameter in de
        xthl            ;hl = first argument , stack = load address
        ret             ;go to load address
        page
ovlay:	pop	h	; retadd from pascal
	xthl		; pointer to parm (overlay name)
	inx	h
	shld	pasprm1
	lxi	h,pasprm1
?ovlay:
;
;       entry point for explicit pl/i calls
;       hl = pointer to argument address list
;       first argument is overlay name
;       second argument is load flag, where:
;               lsb on = always load overlay
;               lsb off = load overlay unless it is already in memory
;
        lda     ?dfdrv
        sta     ovfcb   ;set drive byte to default drive
        mov     c,m
        inx     h
        mov     b,m     ;bc = pointer to name parameter
        inx     h
        mov     e,m
        inx     h
        mov     d,m     ;de = pointer to load flag parameter
        inx     b       ;point to possible ':'
        ldax    b       ;get character
        cpi     ':'     ;is there a drive definition?
        dcx     b       ;point back to first byte of name
        jnz     ovlay0  ;jump if no drive defined - use ?dfdrv (set above)
        ldax    b       ;get drive character
        call    upper
        sui     'A' - 1 ;A = 1; B = 2, etc.
        sta     ovfcb   ;set drive byte
        inx     b
        inx     b       ;point past drive and ':' to first byte of name
ovlay0:
        mov     h,b
        mov     l,c     ;hl point to start of name
        shld    nameptr ;for table update later
        mvi     a,true
        sta     preset  ;set preset switch
	call	search	; always check if it's in memory first
        rar
        rc              ;return with no action if overlay is in memory
ovlay1:
        call    loadov
        ret
        page
;
;       search the overlay table for the overlay name pointed to by bc.
;       if found, return true (1).  else return false (0).
;
search:
        mvi     a,maxnst        ;max # of table entries
        sta     novltmp
        lxi     h,ovtab;overlay table
sear0:
        ora     a
        rz              ;if not found, return false
        mov     a,m     ;get first byte of table entry
        ora     a
        jz      sear1   ;empty entry - skip compare
        push    h       ;base of current overlay table entry
        push    b       ;save pointer to overlay name
        call    compar
        pop     b       ;restore pointer to overlay name
        pop     h       ;restore current entry pointer
        ora     a
        jnz     found
sear1:
        lxi     d,oventl        ;number of bytes per overlay table entry
        dad     d       ;hl = address of next overlay table entry
        lda     novltmp
        dcr     a       ;decrement loop count
        sta     novltmp
        jmp     sear0
found:
        lxi     d,loadb
        dad     d       ;hl = load address byte of overlay table entry
        mov     e,m
        inx     h
        mov     d,m
        xchg            ;hl = load address from overlay table entry
        shld    loadadr ;save load address in case loadov not called
        ret             ;with a = true from compar
        page
;
;       load overlay
;
;       start by reading header record
;
loadov:
        lxi     h,ovfcb+1       ;hl = first byte of filename
        mvi     e,8             ;# of chars to move = 8 (fcb name length)
        call    move
        lda     ovfcb
        cpi     'P' + 1 - 'A' + 1
        lxi     b,drverr
        cnc     error   ;report drive error if out of range
        lxi     b,ovfcb
        call    openf
        call    rdsec
        lxi     h,?dbuff+hloadb
        mov     e,m
        inx     h
        mov     d,m
        xchg            ;hl = load address from overlay header
        shld    loadadr
        push    h       ;save load address
        lxi     h,?dbuff+hsizeb
        mov     e,m
        inx     h
        mov     d,m
        pop     h       ;get load address
        dad     d       ;add size
        dcx     h       ;since size is really MP/M pointer to start of bit map
        mov     a,l
        ani     80h
        adi     7fh
        mov     l,a     ;make sure end addr is 1 below sector boundary
        shld    endadr
        call    rdsec   ;read second header record
;
;       see if end address calculated from header overwrites free space
;
chksiz:
        lhld    endadr
        xchg
	lxi	h,0	; check against start of free space
	dad	sp
        mov     a,e
        sub     l
        mov     a,d
        sbb     h
        jc      update  ;ok if ?memry > endadr
        lxi     b,sizerr
        call    error
        page
;
;       remove any entries which will be overlapped by overlay being loaded
;       by setting first byte of name to 0
;
update:
        mvi     a,maxnst
        sta     novltmp ;loop counter
        lxi     h,ovtab
        shld    curtab  ;current table entry pointer
up0:
        ora     a
        jz      insert  ;done when count goes to 0
        mov     a,m
        ora     a
        jz      entok   ;skip blank entries (first byte = 0)
        lxi     d,loadb
        dad     d       ;hl points to load address bytes in current ovtab ent
ry
        mov     e,m
        inx     h
        mov     d,m     ;de = load address from table
        inx     h
        mov     c,m
        inx     h
        mov     b,m     ;bc = end address from table
        lhld    endadr
        call    comdehl
        jc      entok
        lhld    loadadr
        xchg
        mov     l,c
        mov     h,b
        call    comdehl
        jc      entok
notok:
        lhld    curtab
        mvi     m,0     ;set first byte of name to 0 - overlay is no longer l
oaded
entok:
        lhld    curtab
        lxi     d,oventl
        dad     d       ;point to next entry in overlay table
        shld    curtab
        lda     novltmp
        dcr     a
        sta     novltmp
        jmp     up0
;
comdehl:
        mov     a,l
        sub     e
        mov     a,h
        sbb     d
        ret
        page
;
;       insert name of overlay being loaded into overlay table
;       check for nesting error (too many entries in table)
;
insert:
        lxi     h,ovtab
        mvi     e,maxnst
ins0:
        mov     a,m
        ora     a       ;check first byte of entry
        jz      ins1    ;keep looking for place to insert
        dcr     e
        lxi     b,nsterr
        cz      error   ;no place to insert overlay name
        lxi     b,oventl
        dad     b       ;point to next entry in table
        jmp     ins0
ins1:
        push    h       ;save pointer to table entry
        lhld    nameptr
        mov     c,l
        mov     b,h
        mvi     e,ovnaml
        pop     h       ;get pointer back
        call    move
        mvi     e,oventl-ovnaml
        lxi     b,loadadr
ins2:
        ldax    b
        mov     m,a
        inx     b
        inx     h
        dcr     e
        jnz     ins2
;
;       read overlay according to load address and size in header
;
rdov:
        lhld    loadadr
        push    h       ;set up for rdblk call
        xchg
        lhld    endadr
        mov     a,l
        sub     e
        mov     c,a
        mov     a,h
        sbb     d
        mov     b,a
        inx     b
        lxi     d,ovfcb
        call    rdblk
        lxi     d,ovfcb
        call    close           ;for MP/M systems
        ret
;
rdblk:          ;read a block from the disk into memory
                ;bc = byte count
                ;de = fcbadr
                ;stack = bufadr
        pop     h       ;hl = return addr
        xthl            ;hl = bufadr, stack = return addr
        shld    bufadr
        xchg            ;hl = fcbadr
        shld    fcbadr
        mov     a,c     ;get low (count)
        ani     80h     ;ensure count is even number of sectors
        mov     l,a
        mov     h,b     ;hl = count
        shld    count
disk0:  lhld    count
        mov     a,h
        ora     l
        jz      done    ;done when count = 0
;
        lxi     b,0ff80h
        dad     b       ;subtract 80h
        shld    count   ;count = count - 80h
;
        lhld    bufadr
        mov     e,l
        mov     d,h
        call    setdma
;
        lhld    fcbadr
        mov     d,h
        mov     e,l
        call    diskrd
        ora     a
        lxi     b,rderr
        cnz     error
;
        lhld    bufadr
        lxi     d,sector
        dad     d
        shld    bufadr  ;bufadr = bufadr + sector (80h)
        jmp     disk0
;
done:
        lxi     b,?dbuff
        call    setdma  ;for any subsequent directory manipulation
        ret
;
;       compare overlay name at bc with overlay table name at hl
;       return true (1) if equal, false (0) if not equal
;
compar:
        mvi     e,ovnaml        ;# of chars to compare
comp0:
        ldax    b
        call    upper
        cmp     m
        jnz     ncomp
        inx     h
        inx     b
        dcr     e
        jnz     comp0
        mvi     a,true
        ret
ncomp:
        xra     a
        ret
;
;
;       move string from bc to hl, count in e.
;
move:
        ldax    b
        call    upper
        mov     m,a
        inx     h
        inx     b
        dcr     e
        rz
        jmp     move
;
upper:
        cpi     'a'
        rc
        cpi     'z'+1
        rnc
        ani     0dfh
        ret
;
copyf:          ;copy overlay filename to error message buffer
        lxi     b,ovfcb
        ldax    b       ;get drive byte
        ora     a
        jnz     prf00
        lda     ?dfdrv
prf00:  adi     'A'-1   ;1 = A, 2 = B, etc.
        mov     m,a
        inx     h
        mvi     m,':'
        inx     h
;
        mvi     e,11    ;11 characters in file name
        inx     b       ;skip drive byte
prf0:   ldax    b       ;get next char from fcb
        ani     7fh     ;get rid of any stat bits
        cpi     ' '
        jz      prf1
        mov     m,a
        inx     h
prf1:   dcr     e       ;decrement count
        rz              ;return on count of 0
        inx     b       ;increment fcb pointer
        mov     a,e     ;get count
        cpi     3       ;if there are 3 left, time for a '.'
        jnz     prf0
        mvi     m,'.'
        inx     h
        jmp     prf0
;
rdsec:  ;read a sector into default buffer (used to read header)
        lxi     h,?dbuff
        push    h       ;stack buffadr for rdblk call
        lxi     b,sector
        lxi     d,ovfcb
        call    rdblk   ;read header record of OVL file
        ret
;
openf:          ;open file
        push    b       ;save fcbptr
        call    clrmap  ;clear fcb bytes after filename
        pop     d       ;restore fcbptr
        push    d       ;save it again
        call    open
        inr     a
        pop     d       ;restore fcbptr
        rnz             ;return if open <> 255
        lxi     b,nofile
        call    error
;
clrmap:         ;clear fcb bytes after filename
        lxi     h,12    ;start clearing at 12th byte of fcb
        dad     b       ;hl = .fcb (12)
        xra     a
        mvi     c,21    ;clear 21 bytes  fcb (12) - fcb (32)
clr0:   mov     m,a     ;set byte to 0
        dcr     c       ;decrement count
        inx     h       ;increment pointer
        jnz     clr0
        ret
;
error:          ;report overlay error to pli run time system
        ldax    b       ;get error subcode
        sta     sigsub
        inx     b       ;point to start of error message
        mvi     e,msgsiz
        lxi     h,errmsg
movloop:
        ldax    b
        mov     m,a
        inx     h
        inx     b
        dcr     e
        jnz     movloop
        call    copyf
	mvi	m,'$'
	lxi	d,errmsg
	mvi	c,9
	call	?bdos
        jmp     ?boot
;
open:           ;open file
        mvi     c,15
        jmp     ?bdos
;
close:          ;close file
        mvi     c,16
        jmp     ?bdos
;
diskrd:         ;read a sector
        mvi     c,20
        jmp     ?bdos
;
setdma:         ;set dma address
        mvi     c,26
        jmp     ?bdos
        page
;
;       data area
;
        dseg
;
pasprm1:	ds	2
novltmp:        ds      1       ;loop counter in search
curtab: ds      2       ;points to current ovtab entry
nameptr:        ds      2
loadadr:        ds      2
endadr: ds      2
preset: db      false   ;preset by explicit ?ovlay call flag
?dfdrv:	db	0
ovfcb:
        db      0
        db      '        '
        db      'OVL'
        ds      21
;
ovtab:
        rept    maxnst
        rept    oventl
        db      0
        endm
        endm
;
;       disk i/o parameters
;
bufadr: ds      2
fcbadr: ds      2
count:  ds      2
dmaadd: ds      2
;
;       signal data area
;
siglst: dw      sigcod
        dw      sigsub
        dw      sigfil
        dw      sigaux
;
sigcod: db      0       ;error code
sigsub: ds      1       ;subcode (8-12)
sigfil: dw      0
sigaux: dw      sigmsg
;
sigmsg: db      255     ;count
        db      'OVERLAY, '
errmsg: ds      msgsiz
        ds      14      ;filename - d:filename.OVL
        db      0       ;terminator
;
;       error messages
;
drverr: db      9, 'DRIVE   '
sizerr: db      10,'SIZE    '
nsterr: db      11,'NESTING '
nofile: db      8, 'NO FILE '
rderr:  db      12,'READ    '
;
        end
E 1
