* GPL Routine >25 - Access Direct Output File
*
* This procedure writes information to the disk
* from the caller's buffer.
*
* Inputs:
*    >834C - SCSI device number and buffer bit
*    >834D - Access code
*    >834E - Pointer to file name
*    >8350 - Additional info
*
* Outputs:
*    >8350 - Error code
*              0 = success
*              non 0 = error
*
GPL25
       ANDI R12,>FF00
       AI   R12,24

       BL   @MAKEFN

* First check the access code to see if we're transfering
* data or file parameters.
*
       MOVB @>834D,R1
       JNE  GPL25B

* We're just transferring file parameters.  We will store
* the information and then call MKFDR to put the FDR on disk.
*

       MOVB @>8350,R2        Get pointer to additional info
       SRL  R2,8
       AI   R2,>8300+2
       LDCR @B02,4
       MOVB *R2+,@MKFSZ   # of sectors
       MOVB *R2+,@MKFSZ+1
       MOVB *R2+,@MKFLAG  File flags
       MOVB *R2+,@MKFRPS  # of rec/sec
       MOVB *R2+,@MKFEOF  EOF offset
       MOVB *R2+,@MKFRL   Logical record size
       MOVB *R2+,@MKFL3   # of level 3 records
       MOVB *R2+,@MKFL3+1

       BL   @SAVPAD
       BL   @MKFDR
       BL   @RESPAD
       MOVB @B01,@>8350
       CI   R1,0
       JNE  GPL25A

       MOVB @ZERO,@>8350     Set success code
GPL25A B    @DSRRT

* Here we have to store actual data to the file from
* the buffer
*

GPL25B
       BL   @SAVPAD      Save contents of scratch pad RAM
       BL   @GETFDR
       CI   R5,0             See if file exists
       JEQ  G25ERR

* Let's start off by copying the FDR to a buffer in another bank
*
       LI   R4,DFDR
       LI   R0,256
GPL25C LDCR @ZERO,4
       MOV  *R5+,R3
       LDCR @B02,4
       MOV  R3,*R4+
       DECT R0
       JNE  GPL25C

       BL   @RESPAD

* Register Usage throughout the rest of the subprogram
*
* R1 - # of sectors left to be write
* R4 - Current AU within file
* R5 - Current sector within AU
* R6 - SCSI ID
* R7, R8 - SCSI sector number to read
* R10 - Pointer to buffer (if CPU RAM)

       MOVB @>834D,R1
       SRL  R1,8
       MOVB @>834C,R6
       ANDI R6,>0F00
       AI   R6,->0100

       MOVB @>8350,R2        Get pointer to additional info
       SRL  R2,8
       AI   R2,>8300

* If the buffer is in VDP RAM, set the VDP read address now
*

       MOV  *R2,R10
       MOVB @>834C,R3
       ANDI R3,>8000
       JNE  GPL250
       SWPB R10
       MOVB R10,@VDPWA
       SWPB R10
       MOVB R10,@VDPWA
GPL250

       CLR  R4
       MOV  @2(R2),R5        Get sector number
       JEQ  GPL251           Save a divide instruction maybe

       MOV  R6,R3
       SRL  R3,8
       SLA  R3,1
       LDCR @B04,4
       DIV  @SAUTBL(R3),R4
GPL251
* Now search through the FDR for actual AU on disk.
*
       LDCR @B02,4
       LI   R3,DFDR+40

GPL25D MOV  *R3+,R2
       CI   R4,0
       JEQ  GPL25F
G25DD  C    R2,*R3
       JNE  GPL25E
       INCT R3
       DEC  R4
       JMP  GPL25D

G25ERR
       MOVB @B01,@>8350      Set an error code
       B    @DSRRT

GPL25E INC  R2
       DEC  R4
       JNE  G25DD

GPL25F MOV  R2,R4            R4 now has actual AU

* Now lets write data to the disk
*
GPL25Z LI   R2,SECBUF
       MOV  R4,R7
       LDCR @B04,4
       MOV  R6,R3
       SRL  R3,8
       SLA  R3,1
       MPY  @SAUTBL(R3),R7

       A    R5,R8
       JNC  GPL25G
       INC  R7
GPL25G
       SRL  R8,1
       JNC  GPL25H
       AI   R2,>100
GPL25H SRL  R7,1
       JNC  GPL25I
       AI   R8,>8000
GPL25I

* Let's see if we can write out a 512 byte block and
* save ourselves an extra read and write.

       CI   R1,1             See if we have only 1 sector left
       JEQ  G25I1
       CI   R2,SECBUF        Are we starting in the middle?
       JNE  G25I1
       MOV  R5,R0
       INC  R0
       C    R0,@SAUTBL(R3)
       JNE  GPL25P
G25I1
* Save the contents of scratch pad RAM before
* SCSIRD trashes it

       BL   @SAVPAD

       BLWP @BANKIT
       DATA SCSIRD
       JNE  G25ERR

       BL   @RESPAD

* Now overlay data into the sector buffer.
* VDP RAM or CPU RAM.

       LI   R0,256
G25I2
       MOVB @>834C,R3
       ANDI R3,>8000
       JNE  GPL25K

* The buffer is in VDP RAM

GPL25J MOVB @VDPRD,*R2+
       DEC  R0
       JNE  GPL25J
       AI   R10,256
       JMP  GPL25L

GPL25K MOVB *R10+,*R2+
       DEC  R0
       JNE  GPL25K

GPL25L

* Now write it back out to disk

       BL   @SAVPAD
       BLWP @BANKIT
       DATA SCSIWT
       JNE  G25ERR
       BL   @RESPAD          Restore it again

       DEC  R1
       JEQ  G25RT

       INC  R5
GPL25N LDCR @B04,4
       MOV  R6,R3
       SRL  R3,8
       SLA  R3,1
       C    R5,@SAUTBL(R3)
       JNE  GPL25Z

       CLR  R5

* We now loop through the FDR to see if we go to next AU

       LDCR @B02,4
       LI   R3,DFDR+42
GPL25M C    *R3,R4
       JEQ  GPL25O
       AI   R3,4
       CI   R3,DFDR+>100
       JL   GPL25M

       INC  R4
       JMP  GPL25Z

G25RT
       CLR  R1
       MOVB R1,@>834D        I don't know if this is right
       MOVB @ZERO,@>8350     Set success code
       B    @DSRRT

GPL25O MOV  @2(R3),R4
       JMP  GPL25Z

**
*
* Here we are writing a full 512 byte block.
*
**

GPL25P
       CLR  R0
       MOVB R6,R0            SCSI ID
       MOVB @>834C,R3        Get CPU or VDP memory flag
       ANDI R3,>8000
       SOC  R3,R0
       ORI  R0,>4000         Select absolute sector size
       MOV  R0,@>834C
       MOV  R10,@>834E       Set buffer address
       MOV  R8,@>8350
       MOV  R7,@>8352

       BL   @SAVPAD
       BLWP @BANKIT
       DATA SCSI20
       BL   @RESPAD

       AI   R10,512
       DECT R1
       JEQ  G25RT

       INCT R5
       JMP  GPL25N

* SAVPAD - Save the contents of scratch pad RAM to
* a buffer in bank 2

SAVPAD LDCR @B02,4
       MOV  R10,@POSIAU       Save R10 for now
       LI   R9,>8300
       LI   R10,G24BUF
SAVPD1 LI   R0,>70
SAVPD2 MOV  *R9+,*R10+
       DECT R0
       JNE  SAVPD2
       MOV  @POSIAU,R10       Restore R10
       LDCR @ZERO,4
       RT

* RESPAD - Restore the contents of scratch pad RAM

RESPAD LDCR @B02,4
       MOV  R10,@POSIAU       Save R10
       LI   R10,>8300
       LI   R9,G24BUF
       JMP  SAVPD1
