* I/O op code 5 - LOAD
*
* This routine loads a program file into the users buffer
*

LOAD0  ANDI R12,>FF00
       AI   R12,24
       BL   @GETFDR
       CI   R5,0         See if the file exists
       JNE  LOAD1

* If we were doing DSK emulation, go on to the next device
*

       ANDI R6,>00FF
       JEQ  LOAD0A
       LDCR @ZERO,4
       DECT @SAVR11
       B    @DSRRT

LOAD0A BL   @DSRERR
       DATA >0700        File Error

* Check the file header to make sure it has the characters
* 'FI' in bytes 28 and 29
*
* We no longer check for 'FI' because the Myarc does not
* always put it in there.

LOAD1
       LDCR @ZERO,4

*      MOV  @28(R5),R1
*      CI   R1,'FI'
*      JEQ  LOAD2
*      BL   @DSRERR
*      DATA >0700        File Error

* Make sure it is a program file
*
LOAD2
       MOVB @12(R5),R1
       ANDI R1,>0100
       JNE  LOAD3
       BL   @DSRERR
       DATA >0200        Bad Open Attribute

* Copy the FDR from the SCSI buffer to DFDR

LOAD3  LI   R2,DFDR
       LI   R3,32
LOAD4  MOV  *R5+,R4
       MOV  *R5+,R7
       MOV  *R5+,R8
       MOV  *R5+,R9
       LDCR @B02,4       Select RAM bank 2
       MOV  R4,*R2+
       MOV  R7,*R2+
       MOV  R8,*R2+
       MOV  R9,*R2+
       LDCR @ZERO,4      Select RAM bank 0
       DEC  R3
       JNE  LOAD4

       MOV  @PABBUF+2,R10    Get VDP buffer address

* Compute the number of bytes in the file
*
       LDCR @B02,4       Select RAM bank 2
       MOV  @DFDR+14,R5  Get number of sectors used by the file
       JEQ  LOAD99       Exit if it is an empty file
       DEC  R5
       MOVB @DFDR+16,R5      Get End of File offset
       JNE  LOAD5
       INC  R5
LOAD5  SWPB R5

* See if the user's buffer is big enough to store the entire
* file.  If it isn't, we will decrease the number of bytes
* we read accordingly.
*
       LDCR @ZERO,4
       C    R5,@PABBUF+6
       JL   LOAD6
       MOV  @PABBUF+6,R5
       JEQ  LOAD99       Exit if buffer is zero bytes long
LOAD6

* Set up the rest of the registers.  They are used as follows:
*
* R1 - Points to data chain in the FDR
* R2 - Current AU that we're reading
* R3 - Current sector within the AU
* R5 - Number of bytes remaining to be read
* R10 - Buffer address in VDP or CPU memory
* R11 - # of sectors per AU on this disk
*

       LDCR @B04,4       Select RAM bank 4
       MOV  R6,R4        Get drive #
       SRL  R4,8
       SLA  R4,1
       MOV  @SAUTBL(R4),R11

       LDCR @B02,4       Select RAM bank 2
       LI   R1,DFDR+40   Point to data chain
LOAD8  MOV  *R1+,R2      Get 1st AU of the file
LOAD9  CLR  R3

* Now begin reading sectors from the file until we have
* read all the bytes in the file!
*

LOAD10 MOV  R2,R7        Get AU we need to read
       MPY  R11,R7           Convert AU to sector
       A    R3,R8            Add in sector within AU
       JNC  LOAD11
       INC  R7
LOAD11 LI   R4,SECBUF
       SRL  R8,1         Convert sector to block #
       JNC  LOAD12
       AI   R4,>100
LOAD12 SRL  R7,1
       JNC  LOAD13
       AI   R8,>8000

* Now check to see if we can read the read a 512 byte block
* directly into VDP RAM.  If so, we will use sector I/O
* routines to read the data.  Otherwise, we use BANKIT to
* store the data in SECBUF first.
*
* We can do 512 bytes if -
*  a) There are at least 512 bytes left to read in the file
*  b) We start reading in the 1st half of SECBUF
*  c) The 2nd half of SECBUF contains nect 256 bytes of file
*
LOAD13
       LDCR @ZERO,4

       CI   R5,512           See how much is left to read
       JL   LOAD14

       CI   R4,SECBUF
       JNE  LOAD14

       MOV  R11,R9
       S    R3,R9
       CI   R9,1
       JNE  LOAD20

* Well, it didn't work out.  We have to read the 512 byte
* block into SECBUF and copy it to VDP memory from there.
*
LOAD14 BLWP @BANKIT      Read the block from the disk
       DATA SCSIRD
       JEQ  LOAD15
       BL   @DSRERR
       DATA >0600        Device error
LOAD15 MOV  R10,R0       Set VDP write address
       ORI  R0,>4000
       SWPB R0
       MOVB R0,@VDPWA        Maybe MOVB R0,*R15?
       SWPB R0
       MOVB R0,@VDPWA

       LI   R0,256
       A    R0,R10       Adjust buffer pointer
LOAD16 MOVB *R4+,@VDPWD  Copy the sector to the user's buffer
       DEC  R5
       JEQ  LOAD99       See if we're done
       DEC  R0
       JNE  LOAD16
       INC  R3
LOAD17
       C    R3,R11            See if we've read all the sectors in this AU
       JL   LOAD10            If not, go back and keep reading

       LDCR @B02,4       Select RAM bank 2
       C    R2,*R1       See if we're at the last AU in this cluster
       JEQ  LOAD18       If so, go to next cluster
       INC  R2           Otherwise, go to next AU
       JMP  LOAD9
LOAD18 INCT R1           Go to next cluster
       JMP  LOAD8


LOAD99 BL   @DSRERR
       DATA 0            No error

**
*
* LOAD20
*
*  This is where we use sector I/O to read 512 bytes
*  directly from the SCSI drive to VDP memory.
*
**

LOAD20
       MOV  R6,R0            Get SCSI ID
       ORI  R0,>4000         Set sector size and VDP memory
*      AI   R0,>100
       MOVB R0,@>834C
       MOVB @B01,@>834D      Read
       MOV  R10,@>834E       Buffer address
       MOV  R8,@>8350        Sector to read
       MOV  R7,@>8352           "       "

       BLWP @BANKIT
       DATA SCSI20
       AI   R5,-512          Adjust # of bytes left to read
       JEQ  LOAD99
       AI   R10,512          Adjust buffer pointer
       INCT R3
       JMP  LOAD17
