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
/
PUBPATCH
/
PUBPTZ10.LBR
/
PUBPATCH.AZM
/
PUBPATCH.ASM
Wrap
Assembly Source File
|
2000-06-30
|
9KB
|
364 lines
.title 'pubpatch.asm 4-13-84 (c) 1984 Plu*Perfect Systems'
.settim 16:19:00
.setdat 11/18/84
.setwid 90
.setlen 60
;11/18/84 minor change to published DDJ version to produce
;relocatable object file, to be relocated using HXRLOAD
.remark ~
-- PUBPATCH --
A CP/M 2.2 BDOS modification to support the PUBlic filetype.
--------------------------------------------
Copyright (c) 1984 -- All rights reserved.
Plu*Perfect Systems
P. O. Box 1494
Idyllwild CA 92349
--------------------------------------------
Attribute bit 2 of a filename signifies a PUBlic file,
accessible by its unambiguous filename from all user
numbers.
PUBlic files are not accessible via the usual ambiguous
filenames (e.g. *.* or ABC.D?F), to prevent unintentional
erasure and avoid directory clutter.
Directory entries for PUBlic files are, however, accessible
via ambiguous filenames by using the BDOS search-for-first,
search-for-next functions with a '?' in the drive-byte of the
fcb. Extended versions of SD and DISK7 displays PUBlic files.
To erase a PUBlic file, use "ERA unambiguous-filename". Or use
DISK7. Or change it to a private file and then erase with a
wildcard erase command.
The PUBLIC.COM utility is available to make files either
PUBlic or private and to list the current PUBlic files.
If another utility is used to set the PUBlic attribute bit,
avoid creating multiple files with the same name on the same
drive, unless all of them are private. (PUBLIC.COM checks
for this situation and prevents a conflict.)
The REName command removes all attributes, so RENaming a
PUBlic file will make it private, R/W, DIR in its original
user number.
~
.page
.remark ~
--- TO INSTALL ---
1a. Determine the BIOSBASE address of your system in memory
by subtracting 3 from the warm-boot address in memory:
DDT
L0
subtract 3 ==> BIOSBASE address
1b. Subtract 1600H to determine the CCPBASE_MEMORY address.
1c. Assemble PUBPATCH for these addresses.
Either: use CDL's MACROIII assembler:
MACROIII PUBPATCH A:DHK
Or: convert the pseudo-opcodes to your assembler's
pseudo-ops and assemble into a HEX file.
e.g. .loc ==> org
= ==> set
=\ ==> ????, etc.
2. Create a system image for the SYSGEN operation.
There are two ways to get the image:
a. Either use SYSGEN to extract a system image from a disk
in the usual manner --
SYSGEN
source drive? A
destination drive? <CR>
SAVE pp ORIG.SYS. Use pp=50 pages or so to get
the entire BIOS.
b. Or generate a new system --
MOVCPM ss * where ss=64 for a 64K system,
SAVE pp ORIG.SYS or whatever you are running.
3. Find the base address of the Command Processor in the image
DDT ORIG.SYS
Look for the command processor at 980H:
You recognize it by two JMP instructions, followed by
the command buffer (containing a Digital Research
copyright notice, in the case of the original CCP):
L980
D980
Call that address CCPBASE_IMAGE (normally 980H).
(If you don't find it, you have a non-standard system, and
your user's manual should have a memory map. See, e.g.,
the Compupro Disk 1 Controller manual, sec. 6.4).
4. Calculate the offset needed to cause the PUBPATCH.HEX file to
load on top of the BDOS image. 'offset' will satisfy:
CCPBASE_IMAGE = CCPBASE_MEMORY + offset
5. Create a new system image containing the patch:
DDT ORIG.SYS
IPUBPATCH.HEX
Roffset
G0
SAVE pp NEWSYS.SYS
6. Finally, put the new system on a FLOPPY disk for testing:
SYSGEN NEWSYS.SYS
<CR>
destination_drive
------------------------------------------------
Code also corrects a CP/M 2.2 bug that caused
Rename, Set Attribute, and Delete File functions
to return 0 status on success instead of 0,1,2,3
per CP/M 2.2 Installation Guide.
------------------------------------------------
~
.page
.phex
bdosbase = .
; Internal BDOS locations:
;
FINDNXT = bdosbase+072Dh
NXENTRY = bdosbase+0605h
CKFILPOS = bdosbase+05F5h
MOREFLS = bdosbase+057Fh
FCB2HL = bdosbase+055Eh
SAMEXT = bdosbase+0707h
STFILPOS = bdosbase+05FEh
SETSTAT = bdosbase+0301h
SAVEFCB = bdosbase+0DD9h
COUNTER = bdosbase+0DD8h
FILEPOS = bdosbase+0DEAh
STATUS = bdosbase+0345h
FNDSTAT = bdosbase+0DD4h
CHKWPRT = bdosbase+0554h
CHKROFL = bdosbase+0544h
FINDFST = bdosbase+0718h
SETFILE = bdosbase+066bh
DIRWRITE = bdosbase+05c6h
CKFILPOS = bdosbase+05f5h
DELFILE = bdosbase+0cd7h
EXTMASK = bdosbase+0dc5h
CLOSEFLG = bdosbase+0dd2h
RDWRTFLG = bdosbase+0dd3h
GETEMPTY = bdosbase+0924h
OPENIT1 = bdosbase+085ah
STRDATA = bdosbase+04bbh
SETSTAT = bdosbase+0301h
IOERR1 = bdosbase+0305h
SETS2B7 = bdosbase+0578h
;
.page
.loc FINDNXT
fnxt0: lxi h,0
shld pflag ;initialize PUBlic & wildcard flags
mov c,h ;0
call NXENTRY
call CKFILPOS
jrz nomatch ;if done
lhld SAVEFCB
xchg ;de=user-fcb
ldax d
cpi 0E5h ;if Getempty fn wants first
jrz fnxt1 ;..deleted file slot in directory
push d
call MOREFLS
pop d
jrnc nomatch ;if no more files
;
fnxt1: call FCB2HL ;hl=directory fcb
lda COUNTER
mov b,a ;b=count
mvi c,0 ;c=byte #
ora a ;COUNTER=0 ==> Search fn
jrz matched ;..so match every entry
;
fnxt2: mov a,c ;get byte #
cpi 13
jrz nxtbyte ;omit S1 byte
ldax d ;get user-fcb char
cpi '?'
jrnz fnxt3
sta qflag ;flag wildcard
jr nxtbyt
;
fnxt3: mov a,m ;get directory-fcb char
cpi 0E5h ;check for blank/deleted file
mov a,c ;A = byte #
jrz chkext ;if a deleted file, omit user # check
ora a
jrnz chkext ;or if not user # byte
inx h ;else check for PUBlic file
inx h
bit 7,m ;..at attribute bit 2
dcx h
dcx h
jrz chkext ;if not PUBlic, match on user #
;
; the file is PUBlic
; -- but is BDOS looking for an empty directory slot?
mov a,b ;if COUNTER=1, this is a Getempty request
dcr a ;
jrz fnxt0 ;..so go to next file
sta pflag ;else flag the file PUBlic,
jr nxtbyt ;..and omit matching user #
;
chkext: cpi 12 ; (A=byte #)
ldax d
jrz tstext ;extent byte(#12) is special case
sub m ;compare the characters
ani 07fh ;..excluding attribute bits
jr extdone
tstext: push b ;check for same extent
mov c,m
call SAMEXT
pop b
extdone:jrnz fnxt0 ;if mismatch, get next file
;
nxtbyt: inx d ;chars match, bump to next byte
inx h
inr c ;byte # ++
djnz fnxt2 ;count--
;
; here if-- COUNTER > 1 and filenames match
;
;Test for PUBlic file and wild-card combination:
; ;flags initially = 0, but
pflag = .+1 ; = COUNTER-1 if PUBlic
qflag = .+2 ; = '?'(3Fh) if '?' in fcb+1...
lxi h,.-.
mov a,l ;if file is PUBlic
ana h ;..and there's a wildcard
;(3Fh & 1...n) ==> NZ
jrnz fnxt0 ;..get next directory entry
;
; here if--
; (a) non-PUBlic filenames match,
; or (b) find-all-files (searchfirst/searchnext functions
; with drive byte = '?')
; or (c) delete unambiguous PUBlic-filename.
;
matched:jmp PATCH1
;
nomatch:call STFILPOS
mov a,l ;l=0ffh
jmp SETSTAT
;
.page
; the ERASE FILE routine -- in a new location
;
; Routine is split, with remainder stuffed
; into free bytes at end of BDOS.
;
ERAFILE:call CHKWPRT ;write-protect aborts
mvi c,12
call FINDFST
eraf1: call CKFILPOS ;check for 'E5' case
rz
call CHKROFL ;read-only file aborts
call FCB2HL
jmp PATCH2
LAST1 = . ;must be <= bdosbase+07BEh
;
;
;Remainder of ERASE routine goes at end of BDOS
;
.loc bdosbase+0deeh ;there are 18 spare bytes
PATCH2:
eraf2: mvi m,0E5h ;install erase mark
mvi c,0
call SETFILE ;clear file's space in bitmap
call DIRWRITE ;write directory sector
eraf3: call FINDNXT ;look for next entry
jmp eraf1
LAST2 = . ;must be <= bdosbase+0E00h
;
.page
;rewrite last part of bdos GETNEXT routine to gain space
;
.LOC bdosbase+0971h
;
gnxt0: jrz gnxt1 ;( overlaying jz gtnext1)
mov b,a ;extent byte
lda EXTMASK
ana b
lxi h,CLOSEFLG
ana m
jrz gnxt2 ;must read next extent
gnxt3: call OPENIT1 ;open current extent
gnxt4: call STRDATA ;update rec#, extent#,...
xra a
jsetst: jmp SETSTAT
;
; have overflowed normal extent, check s2 byte
gnxt1: inx h ;shorter code, replacing
inx h ;lxi b,2 & dad b
inr m ;bump s2 byte
mov a,m
ani 0fh
jrz gnxt5 ;error if too many extents
gnxt2: mvi c,15 ;open the next extent
call FINDFST
call CKFILPOS
jrnz gnxt3
lda RDWRTFLG ;no extant extent
inr a ;..if reading, can't open one
jrz gnxt5
call GETEMPTY ;writing, so get next free entry
call CKFILPOS
jrnz gnxt4 ;and if no error, save the data
gnxt5: call IOERR1 ;set error &
jmp SETS2B7 ;..don't close file
;
;
; use space (14 bytes) for fragment from FINDNXT routine:
;
PATCH1: lda FILEPOS
ani 03h
sta STATUS ;save its directory buffer index
lxi h,FNDSTAT
;
.remark ~
The original CP/M 2.2 code removed below is erroneous, and
causes BDOS Erasefile, Renamefile, Setattribute functions
to return A=0 on success rather than the directory index
(0,1,2 or 3) specified in the Interface Guide.
;; mov a,m
;; ral
;; rnc
;; xra a
~
;
mov m,a ;also save it for use
ret ;..by Erase,Rename,Set Attribute fns
;
LAST3 = . ;must be <= bdosbase+09BCh
;
;
;patch ERAFILE reference to its new location
;
.loc (DELFILE+3)
CALL ERAFILE
;
.end