        SUBT    > <wini>arm.FileSwitch.OSFile - Whole file operations

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; +                                                                           +
; +                             F I L E    S W I                              +
; +                                                                           +
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; FileEntry. Vectored SWI level entry
; =========
;
; Corresponds to BBC OSFile. Use temporary Filing System (generally current)

; In    r0b   =  OSFile type
;       r1    -> space or CtrlChar terminated filename. Will be translated
;       r2-r5 =  parms for OSFile

;   &FF Load file using File$Path
;     0 Save file
;     1 Write cat info
;     2 Write load addr
;     3 Write exec addr
;     4 Write attributes
;     5 Read cat info using File$Path
;     6 Delete object
;     7 Create file
;     8 Create directory
;     9 DateStamp file
;    10 Save file setting DateStamp
;    11 Create file setting DateStamp
;    12 Load file using path string
;    13 Read cat info using path string
;    14 Load file using path variable
;    15 Read cat info using path variable
;    16 Load file, no path
;    17 Read cat info, no path
;    18 Set file type
;    19 Create error from object type + name

; Out   VC : r1 preserved
;            Load and ReadInfo ops return
;              r0 object type, r2-r5 cat info
;            Delete returns
;              r0 object type, r2-r5 cat info (file info before deletion)
;            All other ops preserve registers
;       VS : fail

FileEntry NewSwiEntry "r0-r5, r6" ; Results poked into stack

 [ debugosfile
 DREG r0,"OSFile: rc ",cc
 TEQ r0, #OSFile_ReadInfo
 TEQ r0, #OSFile_Delete
 TEQNE r0, #OSFile_SetStamp
 BEQ %FT9901
 TEQ r0, #OSFile_SaveStamp ; only r4,r5 relevant
 TEQNE r0, #OSFile_CreateStamp
 BEQ %FT9900
 DREG r2," r2 ",cc
 TEQ r0, #OSFile_SetType ; only r2
 BEQ %FT9901
 DREG r3," r3 ",cc
 TEQ r0, #OSFile_Load ; only r2,r3
 TEQNE r0, #OSFile_CreateDir
 BEQ %FT9901
9900
 DREG r4," r4 ",cc
 DREG r5," r5 ",cc
9901
 DSTRING r1,": filename "
 ]

10 ; Reentry point for below

        CMP     r0, #OSFile_Load        ; >>>a186<<< changed from RangeCheck
        CMPNE   r0, #OSFile_MakeError
        BHI     %FA01                   ; Give error, no deallocate needed

        BL      TransNameIntoBuffer     ; Translate into PassedFilename
        BVS     %FA99 ; SwiExit, no deallocate needed

        ADR     r6, fileblock_base      ; Save the file parms away for later
        STMIA   r6, {r2-r5}             ; Keep r6 valid at top level
 [ debugframe
 DREG r6, "Thinks fileblock_base at "
 ]

        CMP     r0, #OSFile_Load        ; Fudge this particular op
        JTAB    r0, NE, OSFile
        B       Load_UseLoadPath        ; You cheatin' git !

                                        ; Check values against &.Hdr.File

        JTE     BoringFileOp,           OSFile_Save
        JTE     BoringFileOp,           OSFile_WriteInfo
        JTE     BoringFileOp,           OSFile_WriteLoad
        JTE     BoringFileOp,           OSFile_WriteExec
        JTE     BoringFileOp,           OSFile_WriteAttr
        JTE     Read_UseLoadPath,       OSFile_ReadInfo
        JTE     BoringFileOp,           OSFile_Delete
        JTE     BoringFileOp,           OSFile_Create
        JTE     BoringFileOp,           OSFile_CreateDir
        JTE     StampFileOp,            OSFile_SetStamp
        JTE     SaveCreateStampFileOp,  OSFile_SaveStamp
        JTE     SaveCreateStampFileOp,  OSFile_CreateStamp
        JTE     Load_UseGivenLoadPath,  OSFile_LoadPath
        JTE     Read_UseGivenLoadPath,  OSFile_ReadPath
        JTE     Load_UseGivenLoadPathVar, OSFile_LoadPathVar
        JTE     Read_UseGivenLoadPathVar, OSFile_ReadPathVar
        JTE     Load_UseNoLoadPath,     OSFile_LoadNoPath
        JTE     Read_UseNoLoadPath,     OSFile_ReadNoPath
        JTE     SetTypeFileOp,          OSFile_SetType
        JTE     MakeErrorOp,            OSFile_MakeError

01      CMP     r0, #&FF                ; Silly bits set ?
        ANDHI   r0, r0, #&FF            ; r0b is reason code
        BHI     %BT10                   ; Reenter

        addr    r14, ErrorBlock_BadOSFileReason
        B       %FA9999 ; SwiExit with r14 -> error

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; All the various ReadInfo ops

Read_UseNoLoadPath ; Try to read cat info of this file

        ADR     r4, OSFileNullPrefix    ; Null path string

Read_UseGivenLoadPath ; Try to read cat info along given path string

        MOV     r2, r4
        BL      ExPathString
        B       DoneTheRead


Read_UseGivenLoadPathVar ; Try to read cat info along given path variable

        MOV     r2, r4
        BL      ExPathVariable
        B       DoneTheRead


Read_UseLoadPath ; Try to read cat info along File$Path

        addr    r0, FilePathVariableNameCR
        ADD     r2, r0, #(FilePathVariableDefault - FilePathVariableNameCR)
        BL      ExPathWithDefault

; .............................................................................
; In    PassedFilename allocated
;       FullFilename and SpecialField allocated if no error and object exists

DoneTheRead

        BVS     UpdatingOSFileExit_PF   ; Neither special or fullname allocated

        CMP     r0, #object_nothing
        BNE     UpdatingOSFileExit_PF_FF_SF
        B       UpdatingOSFileExit_PF


LoadActionPrefix        DCB     "Alias$@LoadType_" ; 0 (shared zero)
OSFileNullPrefix        DCB     0
LoadActionErrorString   DCB     "load", 0
                        ALIGN

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Now all the LoadFile ops

Load_UseNoLoadPath ; Try to load this file

        ADR     r4, OSFileNullPrefix    ; Null path string

Load_UseGivenLoadPath ; Try to load along given path string

        MOV     r2, r4
        BL      ExPathString
        B       DoTheLoad

Load_UseGivenLoadPathVar ; Try to load along given path variable

        MOV     r2, r4
        BL      ExPathVariable
        B       DoTheLoad

Load_UseLoadPath ; Try to load along File$Path

        addr    r0, FilePathVariableNameCR
        ADD     r2, r0, #(FilePathVariableDefault - FilePathVariableNameCR)
        BL      ExPathWithDefault

; .............................................................................
; In    fsforthisop set up, r1 -> stripped filename to use
;       PassedFilename allocated
;       FullFilename and SpecialField allocated if no error and object exists

DoTheLoad

        BVS     UpdatingOSFileExit_PF   ; Neither special or fullname allocated

        CMP     r0, #object_file        ; Needs to be a file to be loaded
        BNE     %FT90                   ; Deallocates PF FF SF

        LDMIA   r6, {r2-r5}             ; Load all the file's attributes
        TST     r5, #read_attribute     ; Can only load files with R attribute
        BEQ     %FT96                   ; So there !

        LDRB    r14, [fp, #4*3]
        TEQ     r14, #0                 ; LSB of exec = 0 -> load at specified
        LDREQ   r2, [fp, #4*2]
        BEQ     Load_FileAtR2           ; else interpret 'load at own'

; ---------------- Suss how to load this file 'at own address' ----------------

 [ debugosfile
 DSTRING r1, "File to load at own address is "
 Push r1
 LDR r1, FullFilename
 DSTRING r1, ", fullfilename is "
 Pull r1
 ]
        CMP     r2, #0
        CMPNE   r2, #-1
        CMPEQ   r3, #-1                 ; Is it a command file (execaddr = -1)?
        LDREQ   r2, =&FFFFFE00+&FF      ; Pretend to be dated if so. Make # too

        CMN     r2, #&00100000          ; Is the file date stamped ? CSet if so
        BCC     Load_FileAtR2

        MOV     r0, r2, ASR #8          ; File type now in the lowest 12 bits
        CMP     r0, #&FFFFFFF8          ; The only special file type for load
        MOVEQ   r2, #&8000              ; Which is always loaded at 32K
        BEQ     Load_FileAtR2           ; Type FF8

; .............................................................................

Load_UnrecognisedFile

        addr    r3, OSFileNullPrefix    ; Null postfix for 'l$t_nnn filename'
        addr    r4, LoadActionPrefix
        addr    r5, LoadActionErrorString
        BL      ReadActionVariable      ; Leaves r0 -> action vbl (pushed)
        BVS     UpdatingOSFileExit_PF_FF_SF

        SWI     XOS_CLI
        BLVS    CopyError

        ADR     r0, ActionVariable
        BL      SFreeLinkedArea         ; Accumulate V

        B       LoadedFile

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; r2 = load address, r4 = file length

Load_FileAtR2

        STR     r2, fileblock_load
        ADD     r5, r2, r4              ; End address
        BL      ValidateR2R5_WriteToCore

        MOVVC   r0, #fsfile_Load        ; Always loads at r2
        BLVC    CallFSFile


LoadedFile

        MOVVC   r0, #object_file        ; It was a file, your honour
                                        ; (There exist lying FS's eg. bbc#adfs)

; .............................................................................
; In    PassedFilename, FullFilename and SpecialField to be deallocated

UpdatingOSFileExit_PF_FF_SF

        BL      SFreeFullFilename       ; Deallocate please

; .............................................................................
; In    PassedFilename and SpecialField to be deallocated

UpdatingOSFileExit_PF_SF

        BL      SFreeSpecialField       ; Deallocate please

; .............................................................................
; In    PassedFilename to be deallocated

; Update user registers r0,r2-r5 on all Load/ReadInfo/Delete ops

UpdatingOSFileExit_PF

        BL      SFreePassedFilename     ; Deallocate please
        BVS     %FA99 ; SwiExit, deallocate done

        LDR     r1, [fp, #4*1]          ; Load this so we can go ...
        LDMIA   r6, {r2-r5}             ; r6 -> fileblock_base
        STMIA   fp, {r0-r5}             ; Return to caller
 [ debugosfile
 DREG r0,"OSFile : type ",cc
 DREG r2," load ",cc
 DREG r3," exec ",cc
 DREG r4," size ",cc
 DREG r5," attr "
 ] 
        SwiExit


90      LDR     r1, PassedFilename      ; Use translated name for error gen
        CMP     r0, #object_directory   ; When unsure of object type
        BEQ     %FT91

        BL      SetMagicFileNotFound    ; FullFilename and SpecialField not all
        B       UpdatingOSFileExit_PF

91      BL      SetMagicIsADirectory    ; r1 from above
        B       UpdatingOSFileExit_PF_FF_SF

96      BL      SetErrorAccessViolation
        B       UpdatingOSFileExit_PF_FF_SF

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Set datestamp on file to current

; In    r1 -> allocated PassedFilename

StampFileOp

        BL      SetFSAndPolice          ; Translation done already
        BVS     %FA99 ; SwiExit, PassedFilename deallocated

        MOV     r0, #fsfile_ReadInfo    ; Read existing file info
        BL      CallFSFile
        BVS     %FA95 ; SwiExit, deallocate PassedFilename + SpecialField

        TEQ     r0, #object_file        ; Needs to be a file to be stamped
        BNE     %FT92                   ; Deallocates PF SF(if r0<>0)

        LDR     r2, fileblock_load      ; Already DateStamped ? CSet if so
        CMN     r2, #&00100000
        LDRCC   r2, =&00000FFD          ; Stamp as type data if not dated
        MOVCS   r2, r2, LSR #8          ; Need type in bottom 12 bits
        BL      SReadTime               ; Read machine date into r2,r3
        STMIA   r6, {r2-r3}             ; Put in fileblock_load,_exec

        MOV     r0, #fsfile_WriteInfo   ; Mutate the operation
        B       BoringFileOpCont        ; fsforthisop set up already. VClear


92      LDR     r1, PassedFilename      ; Use translated name for error gen
        CMP     r0, #object_directory   ; When unsure of object type
        BEQ     %FT93

        BL      SetMagicFileNotFound
        B       UpdatingOSFileExit_PF_SF

93      BL      SetMagicIsADirectory    ; r1 from above
        B       UpdatingOSFileExit_PF_SF

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Make error

; In    r2 = object type (&100 -> make 'dir not found' error)
;       r1 -> allocated PassedFilename

MakeErrorOp

        BL      SetFSAndPolice          ; Translation done already
        BVS     %FA99 ; SwiExit, PassedFilename deallocated

        MOV     r0, r2

        CMP     r0, #object_nothing + &100 ; A special case
        addr    r0, MagicErrorBlock_DirNotFound, EQ
        BEQ     %FT68

        CMP     r0, #object_file
        BNE     %BT92

        addr    r0, MagicErrorBlock_IsAFile

68      LDR     r1, PassedFilename
        BL      MagicCopyError
        B       UpdatingOSFileExit_PF_SF

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Set file type on file to that given

; In    r2 bottom 12 bits are file type to set
;       r1 -> allocated PassedFilename

SetTypeFileOp

        BL      SetFSAndPolice          ; Translation done already
        BVS     %FA99 ; SwiExit, PassedFilename deallocated

        MOV     r0, #fsfile_ReadInfo    ; Read existing file info
        BL      CallFSFile
        BVS     %FA95 ; SwiExit, deallocate PassedFilename + SpecialField

        TEQ     r0, #object_file        ; Needs to be a file to be typed
        BNE     %BT92                   ; Deallocates PF SF(if r0<>0)

        LDR     r5, fileblock_load      ; Already DateStamped ? Not r2, please!
        CMN     r5, #&00100000          ; CSet if so. If not, stamp as well

        MOVCS   r0, #OSFile_WriteLoad   ; Just rewrite load address
        BICCS   r5, r5, #&000FF000      ; Take out current file type
        BICCS   r5, r5, #&00000F00      ; preserving MSB of DateStamp
        ORRCS   r2, r5, r2, LSL #8      ; Don't worry about any top bits in r2
                                        ; as we're ORRing with all ones !

        MOVCC   r0, #OSFile_WriteInfo   ; Rewrite both load + exec addresses
        BLCC    SReadTime               ; with new stamp. Attr unchanged

        STMIA   r6, {r2-r3}             ; Put in fileblock_load,_exec
        B       BoringFileOpCont        ; fsforthisop set up already. VClear

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    r2 bottom 12 bits are file type to set
;       r1 -> allocated PassedFilename

SaveCreateStampFileOp

        BL      SReadTime               ; Read machine date into r2,r3
        STMIA   r6, {r2-r3}             ; And put in fileblock_load,_exec

        LDRB    r0, [fp, #4*0]          ; What was the original op (r0b) ?
        TEQ     r0, #OSFile_SaveStamp
        MOVEQ   r0, #fsfile_Save        ; Mutate the operation as appropriate
        MOVNE   r0, #fsfile_Create

; .............................................................................
; In    r1 -> allocated PassedFilename

BoringFileOp

        BL      SetFSAndPolice          ; Translation done already
        BVS     %FA99 ; SwiExit, PassedFilename deallocated

        TEQ     r0, #fsfile_Save
        BNE     BoringFileOpCont        ; VClear

        Push    r2
        MOV     r2, r4                  ; r4 is start address for save
        BL      ValidateR2R5_ReadFromCore
        Pull    r2
        BVS     %FT95 ; SwiExit, deallocate PassedFilename + SpecialField

; .............................................................................
; In    r1 -> allocated PassedFilename
;       SpecialField allocated

BoringFileOpCont

        CMP     r0, #fsfile_Save        ; Save,Create(Dir),Delete mustn't
        CMPNE   r0, #fsfile_Create      ; have wildcarded leafnames
        CMPNE   r0, #fsfile_CreateDir
        CMPNE   r0, #fsfile_Delete      ; VClear
        BLEQ    SetMagicWildCardIfSo

        BLVC    CallFSFile              ; Attempt to do operation
        BVS     %FT95 ; SwiExit, deallocate PassedFilename + SpecialField

        LDRB    r14, [fp, #4*0]         ; What was the original op (r0b) ?
        TEQ     r14, #OSFile_Delete
        BEQ     UpdatingOSFileExit_PF_SF


95      BL      SFreePassedFilenameAndSpecial

99      SwiExit

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        LTORG

        LNK     $fileprefix.OSFind
