;SYS2/ASM - LS-DOS 6.3 TITLE ; ; This SYS module performs the following functions: ; . OPENs an existing File or Device ; . INITs a new File ; . Checks availability of a specific drive ; . Hashes an 11-byte field (file name & ext) ; . Hashes an 8-byte field (password) ; . Renames a filespec/devspec ; . Gets the address of a device control block ; CR EQU 13 *LIST OFF ;Get SYS0/EQU *GET SYS0/EQU:2 *LIST ON *GET COPYCOM:3 ;Copyright message ; ORG 1E00H ; SYS2 AND 70H ;Strip all but entry RET Z ;Back on zero entry CP 10H ;Check for OPEN JP Z,OPEN CP 20H ;Check for INIT JP Z,INIT CP 70H ;Check for rename JP Z,RENAME CP 30H ;Get a DCB? JR Z,GTDCB CP 40H ;Drive availability? JR Z,CKDRV CP 60H ;Check password hash JR Z,HASHPSWD ; ; Routine to hash a file name ; HASHNAME LD B,11 ;Init for 11 chars XOR A ;Clear for start HNAME1 XOR (HL) ;Modulo 2 addition INC HL ;Bump to next character RLCA ;Rotate bit structure DJNZ HNAME1 ; & loop for field len OR A ;Do not permit a zero JR NZ,HNAME2 ; hash code INC A HNAME2 LD (FILEHASH),A ;Stuff code for later RET ; ; Hash a password ; HASHPSWD LD HL,7 ;Hashing will be from ADD HL,DE ; right to left so EX DE,HL ; point to lo-order LD HL,-1 ;Init shift reg to 1's LD B,8 ;Init for 8-char string HPSWD1 LD A,(DE) ;P/u the next byte PUSH DE ; & save the pointer LD D,A LD E,H LD A,L ;Modulo 2 add bits 0-2 AND 7 ; to bits 4-6 of the RRCA ; 16-bit shift register RRCA RRCA XOR L LD L,A ;Shift shift-register LD H,0 ; left by 4-bits to ADD HL,HL ; isolate bits 4-7 ADD HL,HL ADD HL,HL ADD HL,HL XOR H ;Mod 2 add SR bits 4-7 XOR D ;Mod 2 add new byte LD D,A ;Save tempy for hi-order LD A,L ADD HL,HL XOR H XOR E LD E,A EX DE,HL ;SR result to HL POP DE ;P/u pointer to string DEC DE ; & point to next byte DJNZ HPSWD1 ;Loop for field length XOR A RET ; ; Routine to locate a Device Control Block ; GETDCB LD E,(IX+1) ;P/u the 2-character LD D,(IX+2) ; device name GTDCB LD HL,KIDCB$ ;Point to 1st DCB DEV1 PUSH HL LD A,L ;Point to device ADD A,6 ; name field LD L,A LD A,(HL) ;P/u 1st char of name INC L ;Point to 2nd char CP E ;Compare 1st for match JR NZ,DEV2 ;No match? then loop LD A,(HL) ;1st matches, does 2nd? CP D JR NZ,DEV2 ;Loop if no match POP HL ;Get start of DCB RET DEV2 POP AF ;Pop last DCB start INC L ;Inc to start of next DCB JR NZ,DEV1 ;Bypass if not at end ; ; Device not found in tables ; LD A,8 ;"device not available" OR A RET ; ; Check a drive for availability ; CKDRV PUSH IY ;We use IY in disk I/O CALL @GTDCT ;Get driver routine addr LD A,(IY+0) ;P/u drive vector CP 0C3H ;Ck for enabled JP NZ,CKDR5 ;Bypass if disabled PUSH HL PUSH DE BIT 3,(IY+3) ;Test for HARD drive JR NZ,CKDRV1A ;If so bypass range check LD A,(IY+6) ;Make sure the current CP (IY+5) ; cylinder is in range JR NC,CKDRV1 ;Go if in range CALL @RSTOR ;Restore drive JP NZ,CKDR7A ;Go if error ; CKDRV1 LD D,(IY+5) ;P/u current track LD E,0 ;Set for sector 0 CALL @SEEK ;Set track info to FDC JP NZ,CKDR7A ;Go if error CKDRV1A CALL @RSLCT ;Wait until not busy JP NZ,CKDR7A ;Not there - ret NZ BIT 3,(IY+3) ;If hard drive, bypass JR NZ,CKDR2B ; index pulse BIT 4,(IY+4) ;If "ALIEN" by pass JR NZ,CKDR2B ; test of index pulses IF @MOD4 LD A,(FDDINT$) ;Check 'SMOOTH' state OR A LD A,09 ;Set MSB of count down JR Z,INTRON ;Go if not SMOOTH SRL A ;Divide the count by two DI ENDIF IF @MOD2 LD A,20 ENDIF INTRON LD (CDCNT+1),A ;Store in 'LD H' instruction LD HL,0020H ;Set up count (short) ; ; Test for diskette in drive & rotating ; CKDR1 CALL INDEX ;Test index pulse JR NZ,CKDR1 ;Jump on index BIT 7,(IY+4) ;Check CKDRV inhibit bit JR NZ,CKDR2B ;If on skip index test CDCNT LD H,00H ;CKDRV counter (long) ;Count set from above CKDR2 CALL INDEX ;Test index pulse JR Z,CKDR2 ;Jump on no index IF @MOD4 EI ;OK for INTs now ENDIF LD HL,0020H ;Index off wait (short) CKDR2A CALL INDEX JR NZ,CKDR2A ;Jump on index ; ; Diskette is rotating ; CKDR2B PUSH AF ;Save FDC status CALL @DIRCYL ;Get directory track in D LD HL,SBUFF$ ;Point to HIT buffer LD E,L ;Sector 0 for GAT CALL @RDSSC ;Read the GAT JR NZ,CKDR7 ;Jump on error ; ; Update YFLAG$ for year type ; LD DE,(SBUFF$+0CCH) ;Gat type byte LD A,C ;Drive # to A RLCA ;Rotate it into posn RLCA ;For SET x,(hl) RLCA ; opcode OR 0C6H ;For SET opcode BIT 3,D ;Is disk new type? JR NZ,FIXBIT ;Go if so XOR 40H ;Else make RES opcode FIXBIT LD (BIT1),A ;Save opcode LD HL,YFLAG$ ;Pt to year type flag DB 0CBH ;Either SET or RES BIT1 DB 0 BIT 3,(IY+3) ;If rigid drive, JR NZ,CKDR3 ; bypass the rest LD A,22H ;Add offset ADD A,E LD (IY+6),A ;Max track # to DCT RES 5,(IY+4) ;Set to side 0 BIT 5,D ;Test double sided JR Z,CKDR3 ;Jump if only single SET 5,(IY+4) ;Set for side 2 CKDR3 POP AF ;Recover FDC status CKDR3A RLCA ;Shift write prot to 7 OR (IY+3) ;Merge Soft WP bit AND 80H ;Strip all but 7 LD (OPNCB9+1),A ;Save WP status for OPNCB ADD A,A ;Write prot to carry flg ; CKDR4 EQU $ EI POP DE POP HL CKDR5 POP IY RET INDEX LD A,H OR L JR Z,CKDR7 DEC HL CALL @RSLCT ;Check for index pulse BIT 1,A ;Test index RET CKDR7 POP AF ; CKDR7A OR A ;Set NZ ret JR CKDR4 ; and exit ; ; OPEN a device ; Device Control Blocks are from X'0208' - X'02FF' ; DEVOPEN CALL GETDCB ;Find the DCB named RET NZ ; in the IX pointer ; ; Found the needed Device Control Block ; DEV4 LD B,H ;Xfer dcb vector to BC LD C,L PUSH IX ;User DCB to HL POP HL LD (HL),10H ;Show routed INC HL LD (HL),C ;Stuff dcb vector INC HL LD (HL),B INC HL XOR A ;Zero next 3 bytes LD (HL),A INC HL LD (HL),A INC HL LD (HL),A INC HL LD (HL),E ;Stuff dcb name INC HL LD (HL),D RET ; ; ; OPEN a file ; HL <= the address of a 256-byte buffer ; DE <= the address of a 32-byte FCB ; B <= the logical record length (LREC) ; OPEN CALL LNKFCB@ ;Set up link to dcb OPEN1 LD A,(SFLAG$) ;Stuff current sysflag LD (OPEN14+1),A ; to check later then AND 0F8H ; remove bits 0, 1 & 2 LD (SFLAG$),A LD A,(IX+0) CP '*' ;If name starts with '*', JR Z,DEVOPEN ; it is a device spec LD A,B ;P/u Lrl requested LD (LREC$),A LD (OPNCB4+1),HL ;Stuff disk I/O buffer PUSH IX ;Transfer the filespec POP HL ; into the system CALL XFRSPEC ; buffer area RET NZ ;Return if bad name LD HL,NAME$EXT ;Point to name/ext field CALL HASHNAME ; & hash it (11 chars) LD DE,PSWDBUF ;Point to the password CALL HASHPSWD ; & hash it LD (PW$HASH1),HL ;Stuff owner pswd LD (PW$HASH2),HL ;Stuff user pswd OPEN2 LD A,0 ;P/u drive LD C,A INC A ;Jump if :d entered JR NZ,OPEN3 LD C,A OPEN3 CALL CKDRV ;Drive available? JR NZ,OPEN6 ;Jump if not CALL @HITRD ;Get hash index table RET NZ ;Return if read error ; ; Compare hashed filename/ext with each entry ; in the HIT to see if file is on this drive ; OPEN4 LD A,(HL) ;Bypass HIT entry if OR A ; unused JR Z,OPEN5 PUSH HL ;Not vacant LD HL,FILEHASH ;Point to DEC CP (HL) ;Compare with HIT entry POP HL JR Z,OPEN9 ;Jump if a match else OPEN5 INC L ; bump to next entry JR NZ,OPEN4 ;Loop until 256 bytes ; ; File not on this drive ; OPEN6 CALL TESTDRV ;Bump drive if we can JR C,OPEN3 ;Loop if another to test OPEN7 LD A,24 ;File not found error OR A RET TESTDRV LD A,(OPEN2+1) ;If drive still X'FF', INC A ; then advance to next OR A ;Reset Carry for ret w/o RET NZ ; affecting Z/NZ result INC C ;Bump drive counter LD A,C CP 8 ;Loop end, 8 max RET ; ; Although the HIT entry matched, the filename/ext ; did not (due to a collision). Continue to scan ; the rest of the hash index table. ; OPEN8 POP BC ;Remove ret address and POP HL ; excess registers POP BC CALL @HITRD ;Re-read the hit POP HL RET NZ ;Go on i/o error JR OPEN5 ; ; The hashed name matches, read the directory ; OPEN9 PUSH HL PUSH BC LD B,L ;Set up the DEC CALL @DIRRD JR Z,OPEN10 ;Jump if no error POP BC ; else pop returns POP HL RET ; & exit ; ; Verify that directory entry is this file ; OPEN10 PUSH HL PUSH BC ;Save drive (reg C) ; ; If bit 7 is set, it denotes an extended ; directory entry which does not include ; the filename. Go to next HIT entry if set ; BIT 7,(HL) ;Test for FXDE JR NZ,OPEN8 ;Jump if extended BIT 4,(HL) ;If DIR record spare, JR Z,OPEN8 ; continue to search LD A,5 ;Point to filename/ext ADD A,L ; field in directory LD L,A LD DE,NAME$EXT ;Point to entered name LD B,11 ;Init to check 11 chars OPEN11 LD A,(DE) ;Verify a match CP (HL) ; or no match JR NZ,OPEN8 ;Go to next HIT entry INC HL ; if no match; else bump INC DE ; pointers & loop DJNZ OPEN11 POP BC ;Matches! get drive # LD A,C ; & stuff it LD (OPEN2+1),A POP HL POP AF POP AF PUSH BC ;Save DEC and drive PUSH HL ;Save ptr to dir record LD A,(HL) ;P/u 1st byte of dir rec LD (DIR$INIT),A ;Stuff it AND 7 ;Strip all but protection LD C,A LD B,0 LD A,16 ;Point to update password ADD A,L LD L,A LD DE,(PW$HASH2) ;P/u password hash LD A,(HL) ;P/u owner pswd lo order INC HL PUSH HL LD H,(HL) ;P/u owner pswd hi order LD L,A LD A,(NFLAG$) ;P/u NFLAG$ BIT 7,A ;Check network active bit JR Z,USEPWD LD D,H LD E,L USEPWD XOR A ;Compare password entry SBC HL,DE ; with owner password POP HL WASMAT JR Z,OPEN16 ;Grant access if match LD A,C ;Recover protection CP 7 ;Abort if "no access" JR NZ,OPEN13 ;Have access if not "no" ; ; File is password protected - abort ; OPEN12 POP HL POP BC LD A,25 ;"file access denied" OR A RET ; ; Check if prot is exec only ; OPEN13 LD A,C CP 6 ;Check for EXEC ONLY JR NZ,OPEN16 ;Jump if not OPEN14 LD B,0 ;P/u SFLAG$ entry state BIT 2,B ;Did RUN request open? JR Z,OPEN15 ;Bypass if NOT from RUN LD HL,SFLAG$ SET 1,(HL) ;Show RUN & EXEC file LD A,5 ;Set read access for now OPEN15 LD HL,SET@EXEC ;Set RST vector to turn LD (HL),0C9H ; off DEBUG OPEN16 LD (OPNCB1+1),A ;Stuff access level POP HL ;Ptr to direc record POP BC ;P/u DEC and drive ; ; Routine to open up the fcb from the directory ; HL => directory record in SBUFF$ ; BC => DEC and drive used for directory read/write ; IX => pointer to File Control Block ; OPNCB PUSH IY ;Save IY PUSH HL ;Transfer direc record POP IY ; ptr to IY PUSH BC ;Save DEC and drive CALL OPNCB0 ;Create the opened FCB POP BC LD HL,OPEN14+1 ;If from LOAD, don't do BIT 0,(HL) ; any further checks JR Z,OPNEX1 XOR A OPNEX POP IY RET OPNEX1 BIT 5,(IY+1) ;If file already open JR Z,OPNCB8 ; then set read-only POP IY ; & return "file open... OPNEX2 LD A,(IX+1) ;P/u current attributes AND 0F8H ;Mask off current prot OR 5 ; & replace with READ LD (IX+1),A ;Reset access to READ LD A,41 ;Set "file already open" RET ; ; If access level is > read, set file open flag in ; the directory & note close authority in the FCB. ; OPNCB8 LD A,(IX+1) ;P/u FCB access level AND 7 ;Mask off other junk CP 5 ;Ck READ, EXEC, NONE JR NC,OPNCB10 ;Go if one of the above OPNCB9 LD A,0 ;P/u CKDRV status RLCA ;Was drive write prot? JR C,FRCREAD ;CF = WP SET 5,(IY+1) ;Set file open in direc LD A,(NFLAG$) ;P/u Nflag BIT 0,A ;Check for function ON CALL NZ,@DIRWR ;Write the directory JR NZ,OPNEX SET 6,(IX+0) ;Set close authority ; ; Ck if passed LRL matches directory ; OPNCB10 LD A,(IX+9) ;P/u LRL from FCB & CP (IY+4) ; compare with directory LD A,42 ;Init "LRL open fault JR OPNEX ; ; Disk write protected - Change access to READ ; FRCREAD CALL OPNEX2 ;Change access to READ JR OPNCB10 ; ; This routine creates the open file control block ; OPNCB0 EX DE,HL PUSH IX ;Transfer fcb pointer POP HL LD A,(DE) ;Get DIR+0 AND 20H ;Keep "PDS" bit & show OR 80H ; FCB as open LD (HL),A ;Shove into FCB+0 INC HL LD A,(LREC$) ;P/u lrl OR A ;Test for 0 (256) OPNCB1 LD A,0 ;Now start byte 2 with JR Z,OPNCB2 ; that set by "OPEN16" OR 80H ;Show sector or byte I/O OPNCB2 OR 20H ;Show buffer is empty ; ; Set bit 3 if filespec ended in an ; exclamation point. This causes the ; directory to be updated on every ; file write where the EOF is extended ; OPNCB3 OR 0 LD (HL),A ;Init FCB+1 INC HL XOR A LD (HL),A ;Init FCB+2 with 0 INC HL PUSH DE ;Put address of disk I/O OPNCB4 LD DE,0 ; buf into FCB+3 & FCB+4 LD (HL),E INC HL LD (HL),D INC HL POP DE ;FCB+5 with 0 for LD (HL),A ; lo order next INC HL LD (HL),C ;FCB+6 with drive INC HL LD (HL),B ;FCB+7 with DEC INC HL INC DE ;Point to DIR EOF byte INC DE INC DE LD A,(DE) ;P/u DIR lo order EOF LD (HL),A ; & stuff into FCB+8 INC HL INC DE LD A,(LREC$) ;P/u lrl & stuff LD (HL),A ; into FCB+9 INC HL XOR A LD (HL),A ;Init FCB+10 & FCB+11 INC HL ; with zero for NRN LD (HL),A INC HL SET 4,E ;Point to file EOF LD BC,2 ;Move ERN EX DE,HL LDIR ; and zero BC reg EX DE,HL LD A,5 ;Max 5 extents PUSH AF OPNCB5 LD A,(DE) ;Move starting track LD (HL),A INC HL INC DE LD A,(DE) ;Move grans & offset LD (HL),A INC HL AND 1FH ;Strip out grans INC A ;Bump for zero offset ; ; Add reg A to reg pair BC ; ADD A,C ;Add previous count LD C,A ;Update C JR NC,$+3 ;Go if no carry to B INC B POP AF ;Recover counter DEC A ;Decrement loop RET Z ;Done if moved in 5 PUSH AF INC DE LD A,(DE) ;Test for end of extents CP 0FEH ;Extent in use? JR NC,OPNCB6 ;Jump if not LD (HL),C ;Stuff # of cumulative INC HL ; grans to this LD (HL),B ; allocation into FCB INC HL JR OPNCB5 ;Loop for next ; ; Unused extents - put X'FFFF' in remaining fields ; OPNCB6 POP AF ;Recover counter RLCA ;Make times 4 and RLCA ; fill remaining LD B,A ; extent bytes with OPNCB7 LD (HL),0FFH ; 0FFH INC HL DJNZ OPNCB7 RET ; ; INIT a file ; HL => the address of a 256-byte buffer ; DE => the address of a 32-byte FCB ; B => the logical record length (LREC) ; INIT CALL LNKFCB@ ;Link to FCB LD (OPNCB1+1),A ;Start FCB+1 with 0 LD A,10H ;Init for no prot on LD (INIT0),A ; a new file PUSH HL LD HL,SFLAG$ ;Reset called by RUN bit RES 2,(HL) POP HL CALL OPEN1 ;Can we "OPEN" the file? RET Z ;Return if file existing CP 24 ;Return if error not RET NZ ; "file not found" LD A,10H ;Set dir rec to show INIT0 EQU $-1 LD (DIR$INIT),A ; assigned LD A,(OPEN2+1) ;P/u the drive entry LD C,A INC A ;Jump if a drive entry PUSH AF JR NZ,INIT1 ; was made LD C,A INIT1 POP AF ;Stack integrity CALL CKDRV ;Is this drive available? JR NZ,INIT2 ;Jump if not JR C,INIT2 ; or if write protected CALL @HITRD ;Read hash index table RET NZ ;Return if read error CALL SPRHIT ;Locate spare entry JR Z,INIT4 ;Jump if space XOR A ;Set status of CKDRV=Z INIT2 PUSH AF ;Save last CKDRV status CALL TESTDRV JR C,INIT1 ;Loop if not at end LD A,(OPEN2+1) ;If drivespec not entered INC A ; then "directory full JR NZ,INIT2A POP AF ;Stack integrity JR ERR26 INIT2A POP AF ; else if no drive then JR NZ,ERR32 ; "illegal drive... JR C,ERR15 ; else if write protect ERR26 LD A,26 ; "directory space full" DB 1 ERR15 LD A,15 ;"write protect... DB 1 ERR32 LD A,32 ;"Illegal drive... OR A RET ; ; Found a spare HIT entry position ; INIT4 LD B,L ;Save DEC LD A,(FILEHASH) ;P/u filespec hash LD (HL),A ; & store in HIT CALL @HITWR ;Write updated HIT CALL Z,@DIRRD ;Read that dir record RET NZ ;Return if read error PUSH HL PUSH BC EX DE,HL LD BC,5 ;Move 1st 5 bytes into LD HL,DIR$INIT ; directory record LDIR LD C,17 ;Move filename & password LD HL,NAME$EXT ; info into directory LDIR EX DE,HL LD B,10 ;Put X'FFFF' into 5 ext's INIT5 CALL OPNCB7 ;4 for the ext's & 1 for POP BC ; staarting info CALL @DIRWR ;Write updated directory POP HL RET NZ ;Return if write error CALL OPNCB ; else open the fcb SCF ;Indicate new file RET ; ; Xfer the file spec to system buffer area ; XFRSPEC LD B,19 LD DE,PSWDBUF LD A,20H ;Blank out the filename XSPEC1 LD (DE),A ; field in system buffer INC DE DJNZ XSPEC1 LD A,0FFH ;Set drive to X'FF' for LD (OPEN2+1),A ; checking user entry LD E,NAME$EXT&0FFH ;Xfer file name IF @BLD631 CALL XSPEC8B ;<631> ELSE CALL XSPEC8 ENDIF LD C,A LD A,B SUB 8 ;Any valid chars found? JR NZ,XSPEC3 ;Jump if valid name ; ; Filename was invalid format ; OR 19 ;"illegal file name" RET ; ; Continue to check file spec ; XSPEC3 LD A,C CP '/' ;Ext entered? LD E,FILE$EXT&0FFH LD B,3 CALL Z,XSPEC8A ;Xfer the ext CP '.' ;Password entered? LD E,PSWDBUF&0FFH IF @BLD631 CALL Z,XSPEC8 ;<631>Xfer the password ELSE JR NZ,XSPEC3A LD A,17H ;If a password, set init LD (INIT0),A ; to show "no" prot level CALL XSPEC8 ;Xfer the password ENDIF XSPEC3A CP ':' ;Drive entered? JR NZ,XSPEC6 LD A,(HL) ;P/u drive # SUB '0' ;Convert to binary LD (OPEN2+1),A ;Stuff drive # AND 0F8H ;Must be <0-7> LD A,32 ;"illegal drive #" RET NZ ;Return error if out INC HL ; of range LD A,(HL) ;Does filespec end in XSPEC6 SUB 21H ; exclamation point? LD A,8 ;Init to set bit 3 of JR Z,XSPEC7 ; FCB+1 & jump if "!" XOR A ; else reset if not XSPEC7 LD (OPNCB3+1),A RET ; ; ; XSPEC8 IF @BLD631 LD A,17H ;If a password, set init LD (INIT0),A ; to show "no" prot level XSPEC8B ENDIF LD B,8 XSPEC8A LD A,(HL) ;P/u a filespec character INC HL ; & 1st test for A-Z JR XSPEC10 XSPEC9 LD A,(HL) ;P/u a filespec character INC HL ;Advance to next one CP '0' ;Check for 0-9 RET C CP '9'+1 JR C,XSPEC11 XSPEC10 CP 'A' ;Check for A-Z RET C CP 'Z'+1 RET NC XSPEC11 LD (DE),A ;Character is valid INC DE ;Advance to next one DJNZ XSPEC9 ; & loop LD A,(HL) ;P/u following character INC HL RET ; ; Routine to find a spare HIT entry ; SPRHIT LD A,28H ;Start scan here CALL @SCNHIT ;Call to SYSRES RET ; ; Routine to rename a filespec/devspec ; REN0 LD A,18H LD (WASMAT),A OR A ;Denote "file not in dir RET RENAME CALL LNKFCB@ ;Save regs & link to IX LD A,(IX+0) ;If a device, use the SUB '*' ; "device" routine JR Z,RENDEV CP 'R'!80H-'*' ;Special open condition? JR Z,REN0 ;Go if so PUSH HL ;Save new pointer LD HL,SFLAG$ ;Set don't test flags SET 0,(HL) CALL OPEN1 ;Open the "old" spec POP HL RET NZ ;Exit on error LD A,(IX+1) ;Make sure user has AND 7 ; permission to rename CP 3 JR C,REN1 LD A,25H ;"Illegal access... OR A RET ; ; User has access to rename - locate drivespec ; REN1 PUSH HL ;Save start REN2 LD A,(HL) ;P/u char of new spec INC HL CP CR JR Z,REN3 ;Go on ENTER CP 3 JR Z,REN3 ;Go on ETX CP ':' JR NZ,REN2 ;Loop on colon REN3 DEC HL ;Backup to where the LD (HL),':' ; colon should go INC HL ; & force the drivespec LD A,(IX+6) ; to the same as "old" LD C,A ;Keep drive spec in C AND 7 ADD A,'0' ;Make it an ASCII digit LD (HL),A INC HL LD (HL),CR LD B,(IX+7) ;Get DEC POP IX ;Put "new" FCB into IX PUSH BC ; & save DEC & drive LD HL,SFLAG$ ;Set don't test flags SET 0,(HL) CALL OPEN1 ;Open the "new" spec POP BC JR NZ,REN4 ;Should error here REN3A LD A,19 ; or else return OR A ; if "new" is existing RET ; & we opened it REN4 CP 24 ;If not "file not found" RET NZ ; then is error CALL @DIRRD ;Read "old's" directory RET NZ PUSH BC ;Save drive spec LD D,H ;Xfer buffer hi LD A,L ADD A,5 ;Pt to filename field LD E,A ;Set buffer lo LD HL,NAME$EXT ;Point to where the LD BC,11 ; new name is stored LDIR ;Move in new name POP BC CALL @DIRWR ;Rewrite the directory CALL Z,@HITRD ;Read the HIT RET NZ LD D,H ;Set the buffer hi LD E,B ;Set the exact HIT lo LD HL,NAME$EXT ;This doesn't change C CALL HASHNAME ;Hash the new name LD (DE),A ;Stuff code into HIT JP @HITWR ;Rewrite & exit ; ; Routine to rename a device ; RENDEV PUSH HL ;Save new pointer CALL GETDCB ;Locate old in tables POP IX ;Recover pointer to "new" RET NZ ;Back if not in tables LD A,L CP DCBKL$ ;Ck if protected device LD A,40 ;"Protected system device RET C LD A,(IX+0) ;"new" must be a device CP '*' JR NZ,REN3A ;"illegal file name... PUSH HL ;Save address of "old" CALL GETDCB ;Ck if "new" is unused POP HL ;Rcvr address of "old" JR Z,REN3A LD BC,6 ;Point to name field ADD HL,BC ; of "old" device LD (HL),E ;Stuff new name into INC HL ; device control block LD (HL),D XOR A ;Set Z-flag RET ; ; Parameter storage area ; IF @BLD631 ELSE FILEHASH DS 1 ENDIF PSWDBUF DS 8 NAME$EXT DS 8 FILE$EXT DS 3 PW$HASH1 DS 2 PW$HASH2 DS 2 DW 0 ;ERN init DIR$INIT DB 0,0,0,0 IF @BLD631 LAST EQU $ LREC$ DS 1 ;<631> FILEHASH DS 1 ;<631> ELSE LREC$ DS 1 LAST EQU $ ENDIF IFGT $,DIRBUF$ ERR 'Module too big' ENDIF ORG MAXCOR$-2 DW LAST-SYS2 ;Overlay length ; END SYS2