title SDRU2 -- set drive and user for files in program ; copyright 1983 Michael M Rubenstein ; installs a filter to redirect certain files to a specified drive/user. ; is appended to start of program and moves it down ; zcpr solves the problem of making a single copy of a program available ; to all user numbers, but many programs require overlays or work files ; which must also be made accessable. ; up to 8 files may be redirected. ; known limitations: ; requires CP/M 2.2 or higher ; requires Z80 processor ; untested under CP/M Plus ; will not work with programs (such as MultiPlan) which modify the drive ; spec in the fcb after opening. .z80 entry sdru2 false equ 0 true equ not false base equ 0000h ;standard cpm base boot equ base ;warm boot iobyte equ 0003h+base ;i/o byte cpmdsk equ 0004h+base ;current cpm disk bdos equ 0005h+base ;entry to bdos cpmfcb equ 005ch+base ;default cpm fcb cpmbuf equ 0080h+base ;default cpm buffer tpa equ 0100h+base ;start of transient pgm reset equ 0 ;system reset rdcon equ 1 ;read console wrcon equ 2 ;write console rdrdr equ 3 ;read reader wrpun equ 4 ;write punch wrlst equ 5 ;write list conio equ 6 ;console i/o getiob equ 7 ;get i/o byte setiob equ 8 ;set i/o byte wrstr equ 9 ;put string to console rdstr equ 10 ;get a string from con cnstat equ 11 ;console status getver equ 12 ;get cp/m version numb resetd equ 13 ;reset disk system seldsk equ 14 ;select disk opnfle equ 15 ;open disk file clsfle equ 16 ;close disk file search equ 17 ;get first disk file ;(ambiguous reference) snext equ 18 ;get next disk file delfle equ 19 ;delete disk file rdseq equ 20 ;read disk sequential wrseq equ 21 ;write disk sequential makefl equ 22 ;create a file rename equ 23 ;rename disk file glogin equ 24 ;return login vector curdsk equ 25 ;return current disk setdma equ 26 ;set dma for dsk access getalc equ 27 ;return disk alloc vect wrprot equ 28 ;write protect disk getro equ 29 ;get read only vector setfla equ 30 ;set file attributes gdprm equ 31 ;get disk parm ucode equ 32 ;set/get user code rdrand equ 33 ;read random record wrrand equ 34 ;write random record fsize equ 35 ;comp virt file size setrnd equ 36 ;set random record resdrv equ 37 ;reset drive wrranz equ 40 ;write random with zero fill ; relocation macro (just 'cause i'm lazy) reloc macro n ld hl,(rloc&n+1) add hl,de ld (rloc&n+1),hl endm sdru2: .phase tpa begin: jp start dw length ;length of this module pgmlen: dw 0 ;filled in by during installation pgm: db 0,0 ;file to load db ' ' db ' ' fssize equ $-pgm rfiles: db 0,0 ;file 1 db ' ' db ' ' db 0,0 ;file 2 db ' ' db ' ' db 0,0 ;file 3 db ' ' db ' ' db 0,0 ;file 4 db ' ' db ' ' db 0,0 ;file 5 db ' ' db ' ' db 0,0 ;file 6 db ' ' db ' ' db 0,0 ;file 7 db ' ' db ' ' db 0,0 ;file 8 db ' ' db ' ' lfiles equ $-rfiles db "***SETDRU2***" ;identification db "Copywrite 1983 Michael M Rubenstein" start: ld sp,stack ld hl,rfiles ;move redirected file specs to filter ld de,wrfls ld bc,lfiles ldir ld hl,(bdos+1) ;compute location to move to ld (obdos+1),hl ;save bdos location ld de,-lfilt add hl,de push hl ;save new location ld de,-filter ;compute relocation factor add hl,de ex de,hl reloc 01 reloc 02 reloc 03 reloc 04 reloc 05 reloc 06 reloc 07 reloc 08 reloc 09 reloc 10 reloc 11 reloc 12 reloc 13 reloc 14 reloc 15 reloc 16 reloc 17 reloc 18 reloc 19 reloc 20 reloc 21 reloc 22 reloc 23 reloc 24 reloc 25 reloc 26 reloc 27 reloc 28 reloc 29 reloc 30 reloc 31 reloc 32 reloc 33 reloc 34 reloc 35 ld hl,filter ;move the filter to high memory pop de ;get location again push de ;and save it again ld bc,lfilt ldir ld hl,load ;set up to move down program ld de,tpa ld bc,(pgmlen) ret ;go to high memory routine ; the following code is moved to high memory before execution filter: rloc01: ld sp,stack ldir rloc02: ld hl,nbdos ;set the bdos to filter ld (bdos+1),hl ld hl,boot ;return address push hl jp tpa ;do the program ;resident filter starts here nbdos: ld a,c ;check the function cp opnfle jr z,opnflt cp clsfle rloc03: jp z,fleflt cp search jr z,opnflt cp delfle jr z,mkflt cp rdseq rloc04: jp z,fleflt cp wrseq rloc05: jp z,fleflt cp makefl jr z,mkflt cp rename jr z,mkflt cp rdrand rloc06: jp z,fleflt cp wrrand rloc07: jp z,fleflt cp fsize rloc08: jp z,fleflt cp wrranz rloc09: jp z,fleflt obdos: jp 0 ;set to old bdos loc ;check file on open for redirection mkflt: or a ;flag for make jr opnfl1 opnflt: scf ;flag for open opnfl1: sbc a,a ;0 for make, ff for open rloc10: ld (oflag),a ld a,(de) ;may already be set to phony cp 17 rloc11: jp nc,flefl2 rloc12 equ $+1 ld (fstack),sp rloc13: ld sp,fstack push bc ;save parameters push de rloc14: ld hl,wrfls ld c,17 ;offset for phony drive inc de ;point to name ckloop: ld a,(hl) ;are we done checking? or a jr z,nored ;yes, no redirection sub a ;set not ambig rloc15: ld (aflag),a push de ;save pointer to name push hl ;save pointer to table ld b,11 ;length of name+type inc hl ;point to name in table inc hl rloc16: cmplp: ld a,(oflag) ;should we consider ambiguous? or a jr z,cmp1 ;not if make ld a,(hl) cp '?' jr nz,cmp1 rloc17: ld (aflag),a jr cmp2 cmp1: ld a,(de) ;compare and 7fh ;strip bit 7 cp (hl) jr nz,notit cmp2: inc hl ;advance pointer to table name inc de ;advance pointer to fcb name djnz cmplp pop hl ;got it, throw away pointer to table pop hl ;throw away pointer to name pop de ;get fcb ld l,c pop bc ;get function rloc18: ld a,(aflag) ;ambiguous? or a jr z,opnfl9 ;go to it if not push hl ;save everything push de push bc rloc19: call obdos cp 0ffh ;ok? jr z,opnfl8 rloc20 equ $+1 ld sp,(fstack) ret opnfl8: pop bc ;restore parameters pop de pop hl opnfl9: ld a,l ld (de),a ;set phony drive jr flefl1 ;now handle the redirection nored: pop de ;no redirection pop bc ;restore parameters rloc21 equ $+1 ld sp,(fstack) ;restore stack jr obdos notit: pop hl ;get pointer to table ld de,fssize ;size of table entry add hl,de ;advance to next entry ld a,c add a,e ;advance phony drive spec ld c,a pop de jr ckloop ; if the file is redirected, fudge it fleflt: ld a,(de) cp 16+1 ;if > max drive, redirected rloc22: jp c,obdos flefl2: cp '?' ;and not ambigous? rloc23: jp z,obdos rloc24 equ $+1 ld (fstack),sp ;save old stack rloc25: ld sp,fstack ;and use local stack flefl1: push bc ;save parameters push de ld c,ucode ;get user number ld e,0ffh rloc26: call obdos rloc27: ld (user),a ;save user number pop hl ;get fcb address again push hl ;and save it ld a,(hl) ;get phony drive spec rloc28: ld (pdrive),a ;save it ld e,a ld d,0 rloc29: ld hl,wrfls-17+1 ;phony drive is entry in table + 17 add hl,de push hl ;save entry in table ld c,ucode ;set user code ld e,(hl) rloc30: call obdos pop hl ;get entry in table pop de ;get fcb again pop bc ;get function dec hl ;point to drive ld a,(hl) ld (de),a push de ;save fcb address push bc ;save function rloc31: call obdos pop bc ;get function again pop de ;get fcb again push af ld a,c cp clsfle ;is this a close? jr z,flefl9 ;don't reset phony spec if so rloc32: ld a,(pdrive) ;reset phony drive spec ld (de),a flefl9: push hl ;save hl return value ld c,ucode rloc33: ld a,(user) ld e,a rloc34: call obdos pop hl ;get real return values pop af rloc35 equ $+1 ld sp,(fstack) ret user: db 0 ;hold user number pdrive: db 0 ;hold phony drive spec oflag: db 0 ;open/make aflag: db 0 ;ambiguous? wfcb: db 0 db ' ' db ' ' db 0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0 wrfls: ds lfiles ;file table db 0 ;to end it all ds 32 fstack: ds 2 ds 16 stack: ds 2 lfilt equ $-filter length equ $-begin load equ ($+7fh) and 0ff80h .dephase end