**
*
*  OPEN OUTPUT
*
*  Here is where we open a file for output.  If the
*  file aready exists, make sure it's not protected
*  and has all the same attributes of the file we
*  want to open.  I no longer deallocate the AU's.
*
*  If the file does not exist, see if the directory
*  exists.  If it does, then create a new entry in
*  the file index
*
**

OPENOU
       BL   @GETFDR           See if the file already exists
       CI   R5,0
       JNE  OOU1
       B    @OOU20

* The file exists
*
OOU1
       LDCR @ZERO,4           Select RAM bank 0
       MOV  @12(R5),R1        Get file flags
       COC  @PROBIT,R1
       JNE  OOU2
       BL   @DSRERR           File protected - error
       DATA >0100

OOU2
       ANDI R1,>0100          Check for Data/Program
       JEQ  OOU3
OOUBAD BL   @DSRERR
       DATA >0200             Bad open attribute

OOU3   MOV  @12(R5),R1        Check Fixed/variable
       ANDI R1,>8000
       MOVB @PABBUF+1,R2
       ANDI R2,>1000
       SLA  R2,3
       C    R1,R2
       JNE  OOUBAD

       MOVB @12(R5),R1        Check Display/Internal
       ANDI R1,>0200
       MOVB @PABBUF+1,R2
       ANDI R2,>0800
       SRL  R2,2
       C    R1,R2
       JNE  OOUBAD

* Now compare record length.  If no record length was
* specified, we can continue.
*
       MOVB @PABBUF+4,R2
       JEQ  OOU4
       CB   R2,@17(R5)
       JNE  OOUBAD
OOU4

* Set up the file cache entry

       BL   @OSCASH

* Reset a few fields in the FDR
*
       LDCR @ZERO,4
*      CLR  @14(R5)           Number of sectors currently allocated
       MOVB @ZERO,@16(R5)     End of file offset
       CLR  @18(R5)           Number of level 3 records allocated

* Write the FDR back out to disk
*
       LDCR @B04,4            Select RAM bank 4
       MOV  @SAVEAU,R7

       BL   @ALOT

       SRL  R8,1
       SRL  R7,1
       JNC  OOU7
       AI   R8,1
OOU7
       BLWP @BANKIT
       DATA SCSIWT
       JEQ  OOU8
       BL   @DSRERR
       DATA >0600             Device error
OOU8

* Copy the FDR to FDR buffer in Bank 5
*
       LDCR @B02,4
       MOV  @4(R4),R1
       LI   R4,256
OOU9   LDCR @ZERO,4
       MOV  *R5+,R2
       LDCR @B05,4
       MOV  R2,*R1+
       DECT R4
       JNE  OOU9

       LDCR @ZERO,4
       B    @DSRRT            File is open!!!

**
*  The specified file does not exist.  We will have to make
*  a new entry for the file in the file index of the directory
*
**

OOU20
       BL   @GETDDR      Get the parent directory
       CI   R5,0
       JNE  OOU21
       BL   @DSRERR      Directory does not exist
       DATA >0700        File error

OOU21  LDCR @B03,4            Select RAM bank 3
       CB   @22(R5),@B127     See if directory is full
       JNE  OOU22
       BL   @DSRERR
       DATA >0400             Out of space error

OOU22  AB   @B01,@22(R5)      Increment file counter

* We will now read the DDR and write it back out with the
* number of files incremented by 1.  In a perfect world,
* we would try to allocate an AU for the file first.
*
       LDCR @B04,4            Select RAM bank 4
       MOV  @SAVEAU,R7        Get AU of the DDR

       BL   @ALOT

       LI   R2,SECBUF
       SRL  R8,1
       JNC  OOU23
       AI   R2,>100
OOU23  SRL  R7,1
       JNC  OOU24
       AI   R8,>8000
OOU24
       BLWP @BANKIT
       DATA SCSIRD
       JEQ  OOU26

OOU25  BL   @DSRERR
       DATA >0600             Device error

OOU26  AB   @B01,@22(R2)      Increment file counter
       BLWP @BANKIT
       DATA SCSIWT
       JNE  OOU25

* Now we have to place an AU for the FDR in the file index.
* We will do a cut-and-paste from the SAVE procedure.  This
* really should be a subprogram since it it duplicated.
*

       MOV  R5,R0            Save pointer to DDR in memory

* I am hardcoding a value of 256 for AU boundry.  I should
* really get this value from the VIB

       LI   R3,-256
       CLR  R7
       LI   R8,1             We want 1 AU
       LDCR @ZERO,4          Select RAM bank 0
       BLWP @ALLOC
       JNE  OOU25            Device error

       CI   R4,0             See if we got no AU's
       JNE  OOU27
       BL   @DSRERR
       DATA >0400            Out of space

OOU27  LDCR @B02,4           Save AU we got allocated
       MOV  R5,@SFDRAU

* We now have to do a binary search on all the
* file names in the directory to see where it will go.
*
       LDCR @B02,4
       LI   R2,NCB+39
OOU28  CB   *R2,@PERIOD
       JEQ  OOU29
       DEC  R2
       CI   R2,NCB-1
       JNE  OOU28

OOU29  INC  R2
       CI   R2,NCB+40        Make sure we don't have a 0 length
       JNE  OOU31            file name
OOU30  BL   @DSRERR
       DATA >0700            File Error
OOU31  CB   *R2,@SPACE
       JEQ  OOU30

* Now copy the filename to FNCB
*
       LI   R1,FNCB
OOU32  MOVB *R2+,R3
       LDCR @ZERO,4
       MOVB R3,*R1+

       LDCR @B02,4
       CI   R2,NCB+40
       JEQ  OOU33
       CB   *R2,@SPACE
       JNE  OOU32

OOU33  LDCR @ZERO,4          Select RAM bank 0
OOU34  CI   R1,FNCB+10
       JEQ  OOU35
       MOVB @SPACE,*R1+
       JMP  OOU34
OOU35

* Now get the file index back so we can insert the AU
* of the new FDR
*

       LDCR @B03,4           Select RAM bank 3
       MOV  R0,R3
       MOV  @24(R3),R7       Get AU of file index

       BL   @ALOT

       LI   R4,SECBUF
       SRL  R8,1
       JNC  OOU36
       AI   R4,>100
OOU36  SRL  R7,1
       JNC  OOU37
       AI   R8,>8000
OOU37
       BLWP @BANKIT          Read the index from disk
       DATA SCSIRD
       JEQ  OOU38
       BL   @DSRERR          Signal error
       DATA >0600            Device error

OOU38  LI   R2,DFDR
       LI   R3,256
OOU39  MOV  *R4+,R5          Copy the index to a buffer
       LDCR @B02,4
       MOV  R5,*R2+
       LDCR @ZERO,4
       DECT R3
       JNE  OOU39

* Now we have to search the index and see where our
* new file will fit in alphabetically
*

       LDCR @B03,4            Select RAM bank 3
       MOV  R0,R3

       MOVB @22(R3),R1        Get # of files in directory
       CLR  R0
       SRL  R1,8
       DEC  R1                Ignore our own file
       JEQ  OOU48
       DEC  R1

OOU40  LDCR @B02,4           Select RAM bank 2
       MOV  R0,R2            Compute the midpoint
       A    R1,R2
       ANDI R2,>FFFE
       MOV  @DFDR(R2),R7     Get AU of FDR
       LI   R4,SECBUF

       BL   @ALOT

       SRL  R8,1
       JNC  OOU41
       AI   R4,>100
OOU41  SRL  R7,1
       JNC  OOU42
       AI   R8,>8000
OOU42

* Read the FDR from disk and compare file names
*
       BLWP @BANKIT
       DATA SCSIRD
       JEQ  OOU43
       BL   @DSRERR
       DATA >0600            Device Error
OOU43
       LI   R2,FNCB
OOU44  CB   *R4+,*R2+
       JL   OOU45
       JH   OOU46
       JMP  OOU44

OOU45  C    R0,R1
       JEQ  OOU47
       MOV  R0,R2
       A    R1,R2
       SRL  R2,1
       MOV  R2,R0
       INC  R0
       JMP  OOU40

OOU46  C    R0,R1
       JEQ  OOU48
       MOV  R0,R2
       A    R1,R2
       SRL  R2,1
       C    R2,R0
       JEQ  OOU48
       MOV  R2,R1
*      JEQ  OOU48
       DEC  R1
       JMP  OOU40

OOU47  INC  R0
OOU48  SLA  R0,1
       AI   R0,DFDR

* Insert the AU of our new FDR into the file index.
*
       LDCR @B02,4           Select RAM bank 2
       LI   R1,DFDR+252
OOU49  C    R1,R0
       JEQ  OOU50
       MOV  @-2(R1),*R1
       DECT R1
       JMP  OOU49

OOU50  MOV  @SFDRAU,*R0      Put in AU of our new FDR in index

* Now write the new file index back out to disk
*

       BL   @GETDDR          Get pointer to DDR back

       LDCR @B03,4           Select RAM bank 3
       LI   R2,SECBUF
       MOV  @24(R5),R7       Get AU of the file index

       BL   @ALOT

       SRL  R8,1
       JNC  OOU51
       AI   R2,>100
OOU51  SRL  R7,1
       JNC  OOU52
       AI   R8,>8000
OOU52
       BLWP @BANKIT
       DATA SCSIRD
       JEQ  OOU53
       BL   @DSRERR
       DATA >0600            Device Error

* Now replace the file index in the SCSI buffer
*
OOU53  LI   R3,DFDR
       LI   R1,256
OOU54  LDCR @B02,4           Select RAM bank 2
       MOV  *R3+,R4
       LDCR @ZERO,4          Select RAM bank 0
       MOV  R4,*R2+
       DECT R1
       JNE  OOU54

       BLWP @BANKIT          Now write back out to disk
       DATA SCSIWT
       JEQ  OOU55
       BL   @DSRERR
       DATA >0600            Device Error
OOU55

* Now we are going to write out a blank FDR to the disk.
* When we are done writing the contents of the file, we
* will re-write the FDR.  I do it this way in case the
* computer crashes when writing the data.  We will not
* have a corrupt FDR.
*

* Allocate an entry in the open file cache and build the FDR
* in bank 5.

       BL   @OSCASH
       MOV  @SFDRAU,@48(R4)  Store the FDR's AU

* Copy the file name into the FDR

       MOV  @4(R4),R1        Get FDR address
       MOVB @2(R4),R10       Get FDR bank
       LI   R2,FNCB
       LI   R3,10
OOU59  LDCR @ZERO,4
       MOV  *R2+,R0
       LDCR R10,4            Select the bank the FDR resides in
       MOV  R0,*R1+
       DECT R3
       JNE  OOU59

OOU61  CLR  *R1+             Extended record length

* Here we set the file flags.  We only need to set the
* variable/fixed bit and internal/display bit.

       CLR  R2
       LDCR @ZERO,4          Select RAM bank 0
       MOVB @PABBUF+1,R0
       ANDI R0,>1000
       JEQ  OOU61A
       ORI  R2,>8000         Variable length records
OOU61A MOVB @PABBUF+1,R0
       ANDI R0,>0800
       JEQ  OOU61B
       ORI  R2,>0200         Internal
OOU61B LDCR R10,4
       MOVB R2,*R1+          File flags

* Compute the number of records per sector by dividing
* the sector size (256) by record size.

       LDCR @ZERO,4
       MOVB @PABBUF+4,R0     Get record size
       JNE  OOU61D
       LI   R0,80*256        Default record size is 80
OOU61D
       SRL  R0,8
       CLR  R7
       LI   R8,256
       DIV  R0,R7
       LDCR R10,4
       SLA  R7,8
       MOVB R7,*R1+          # of records per sector
       CLR  *R1+             # of sectors allocated
       MOVB @ZERO,*R1+       End of file offset
       LDCR @ZERO,4          Get record length
       MOVB @PABBUF+4,R0
       JNE  OOU61C           If 0, use the default of 80
       MOV  @PABADR,R0       Store record length in
       AI   R0,4               caller's PAB
       ORI  R0,>4000
       SWPB R0
       MOVB R0,@VDPWA
       SWPB R0
       MOVB R0,@VDPWA
       MOVB @B80,R0
       MOVB R0,@VDPWD
OOU61C
       LDCR R10,4
       MOVB R0,*R1+
       CLR  *R1+             Level 3 records allocated
       CLR  *R1+             Date & Time of creation
       CLR  *R1+                     "
       CLR  *R1+             Date & Time of update
       CLR  *R1+                     "
       LI   R0,'FI'
       MOV  R0,*R1+
       CLR  *R1+             Pointer to parent AU
       CLR  *R1+             Pointer to offspring AU
       CLR  *R1+             # of AUs for this FDR
       LDCR @B03,4
       MOV  @24(R5),R0       Get pointer to FDIR
       LDCR R10,4
       MOV  R0,*R1+          Pointer to FDIR
       CLR  *R1+             Extended info
OOU62  CLR  *R1+             Clear the data chain
       MOV  R1,R0
       ANDI R0,>00FF         This is ugly, but I'm in a hurry
       JNE  OOU62
       AI   R1,-256          Reset pointer

* Now read the block where the FDR will reside

       LDCR @B02,4           Select RAM bank 2
       MOV  @SFDRAU,R7

       BL   @ALOT

       LI   R4,SECBUF
       SRL  R8,1
       JNC  OOU63
       AI   R4,>100
OOU63  SRL  R7,1
       JNC  OOU64
       AI   R8,>8000
OOU64
       BLWP @BANKIT
       DATA SCSIRD
       JEQ  OOU65
       BL   @DSRERR
       DATA >0600            Device Error

* Now copy our FDR to the SCSI buffer
*
OOU65
       LI   R0,256
OOU66  LDCR @B05,4
       MOV  *R1+,R3
       LDCR @ZERO,4
       MOV  R3,*R4+
       DECT R0
       JNE  OOU66
       AI   R1,-256

       BLWP @BANKIT          Write back out to disk
       DATA SCSIWT
       JEQ  OOU67
       BL   @DSRERR
       DATA >0600             Device Error
OOU67

       LDCR @ZERO,4
       B    @DSRRT            Hooray!  We're done
