;>InitDieSvc

 TTL    "Initialisation, finalisation and service call handling"

; >>>>>>>>>
; InitEntry
; >>>>>>>>>

InitEntry ROUT          ; NO REENTRANCY CHECK NEEDED
        Push    "R7-R11,LR"

        ; Macro to disallow rip-off RAM loaded version (te he ;-)
        ChkKernelVersion

        ; Check if we're the base incarnation and return if we are
        CMPS    R11, #&3000000
        RSBLOS  LR, R11, #0
        Pull    "R7-R11,PC",HS,^

        ; Parameter is ascii string number which is address of
        ; parameter block higher up the stack which we passed
        ; to ourselves.
        MOV     R0, #16
        MOV     R1, R10
        SWI     XOS_ReadUnsigned
        BVS     %FT99
        MOV     R9, R2          ;ptr to stacked parameters

        ; Don't know what this faff's about
        MOV     R10,#1          ;init flag

        ; Save pointer to private word in r11 for use later
        MOV     R11, R12

        ; Pick up contents of parameter block
        LDMIA   R9, {R0-R6}
 [ Debug1
        DLINE   "Parameters read from supplied block:",cc
        DREG    R0,"",cc
        DREG    R1," ",cc
        DREG    R2," ",cc
        DREG    R3," ",cc
        DREG    R4," ",cc
        DREG    R5," ",cc
        DREG    R6," "
 ]
        ; Split out Floppies and Winnies
        AND     R7, R3, #&FF            ;floppies
        LDRB    R8, [R9,#4*3+1]         ;winnies

        ; Lower bound the DirCache size
        CMPS    R4, #CacheMin
        MOVLO   R4, #CacheMin

        ; Evaluate:
        ; r1 = buffer space needed
        ; r2 = process block size
        MOVS    R1, R5, LSL #10 ;using file cache ?
        MOVEQ   R2, #ShortProcessBlk
        BEQ     %FT02           ;no file cache

        ADD     R1, R1, R5, LSL #(10-BufScale)  ;length of file buffers

        MOV     R2, #ProcessPairs+(ExtraPairs+1)*8
 [ {TRUE}
 ; if scatter entry extension disabled number of entries = buffers*4+extrapairs
        ADD     R2, R2, R5, LSL #3 + 2          ;length of process block
 |
        ADD     R2, R2, R5, LSL #3              ;length of process block
 ]

02
        ; Start accumulating in r3 the space needed:
        ; r3=buffer space + 1*process block(for the floppy)
        ADD     R3, R1, R2

        ; Add a process block for the Winnie(s) if needed
        TEQS    R8, #0          ;do we need winnie process block ?
        ADDNE   R3, R3, R2      ;total file cache space

        ; Add enough for the stuff below the DirCache
        MinOps  ADD, ADD, R3, R3, (:INDEX:DirCache)

        ; calc buffer hash table size and add it on (it's first power of 2 gt filecache buffer count)
        MOV     R0, #1
03
        CMPS    R0, R5
        MOVLO   R0, R0, LSL #1
        BLO     %BT03
        ADD     R3, R3, R0, LSL #2

        ;add space for Dir Cache
        ADD     R3, R3, R4

        ;add space for defect maps for all drives, +(4+floppies)*512
        ASSERT  SzDefectList = (1 :SHL: 9)
        ADD     R3, R3, #4 :SHL: 9              ; winnie defect maps
        ADD     R3, R3, R7, LSL #9              ; + floppy defect maps

        Push    "R0-R2"                 ;save file cache lengths

        ; Allocate the main workspace
        MOV     R0, #ModHandReason_Claim
        SWI     XOS_Module              ;claim workspace
        MOV     SB, R2

        ADDVS   SP, SP, #3*4
        BVS     %FT95
        Pull    "R0-R2"

        ; Attach main workspace to private word
        STR     SB, [R11]
        STR     R11, PrivateWord

        sbaddr  R3, DirCache
 [ Debug1
        DREG    SB, "Static base:"
        DREG    R3, "Dir cache:"
 ]

        ; Skip the DirCache, now at file cache
        ADD     R3, R3, R4

 [ Debug1
        DREG    R3, "File cache low limit:"
 ]

        ; Skip file buffers
        ADD     R3, R3, R1

        ; Mark where the file buffers start at the moment
        STR     R3, FileBufsStart

        ; Mark where the file buffers end (also where the floppy process block is)
 [ Debug1
        DREG    R3, "Floppy process block:"
 ]
        STR     R3, FileBufsEnd
        ASSERT  FloppyProcessBlk=FileBufsEnd

        ; Initialise the floppy process block to be inactive
        MOV     R4, #Inactive
 [ DebugP
        DREG    r3, "Process ",cc
        DREG    r4, " going inactive with "
 ]
        STRB    R4, [R3,#Process]
        TEQ     R5, #0
        MOVNE   LR, #0
        STRNE   LR, [R3, #ProcessWriteBehindLeft]
        ASSERT  ProcessWriteBehindDrive :MOD: 4 = 0
        ASSERT  ProcessWriteBehindDisc = ProcessWriteBehindDrive + 1
        MOVNE   LR, #-1
        STRNE   LR, [R3,#ProcessWriteBehindDrive]

        ; Set up the Winnie process block (ARM_CC_Mask used as 'bad process block' indicator')
        ; and initialise it to inactive if there're winnies present
        ADD     R3, R3, R2
        TEQS    R8, #0
        MOVNE   LR, R3
        MOVEQ   LR, #ARM_CC_Mask
        STR     LR, WinnieProcessBlk
 [ Debug1
        Push    "R3"
        MOV     R3, LR
        DREG    R3, "Winnie process block:"
        Pull    "R3"
 ]
 [ DebugP
        DREG    r3, "Process ",cc
        DREG    r4, " going inactive with "
 ]
        STRNEB  R4, [R3,#Process]

        TEQNE   R5, #0
        MOVNE   LR, #0
        STRNE   LR, [R3,#ProcessWriteBehindLeft]
        ASSERT  ProcessWriteBehindDrive :MOD: 4 = 0
        ASSERT  ProcessWriteBehindDisc = ProcessWriteBehindDrive + 1
        MOVNE   LR, #-1
        STRNE   LR, [R3,#ProcessWriteBehindDrive]

        TEQ     r8, #0
        ADDNE   R3, R3, R2


        STRB    R5, MaxFileBuffers
        STRB    R5, UnclaimedFileBuffers

        ; Set up cache buffers and cache hash table
 [ Debug1
        DREG    R3, "Buffer hash table:"
 ]
        STR     R3, BufHash

        ; hash table
        SUB     R0, R0, #1
        STRB    R0, BufHashMask

        ADRL    LR, DummyBuf            ;initialise buffer hash table
05
        STR     LR, [R3], #4
        SUBS    R0, R0, #1
        BPL     %BT05

        ; cache buffers
        sbaddr  R0, BufChainsRoot
        MOV     R1, #6
08
        STR     R0, [R0,#YoungerBuf]
        STR     R0, [R0,#OlderBuf]
        ADD     R0, R0, #ChainRootSz
        SUBS    R1, R1, #1
        BNE     %BT08

        LDMIA   R9, {R0-R2,R4}
        ASSERT  ParentPrivate=ParentBase+4
        ASSERT  Floppies=ParentPrivate+4
        ASSERT  Winnies=Floppies+1
        ASSERT  Drive=Winnies+1
        ASSERT  StartUpOptions=Drive+1
        ASSERT  WinnieSizes=StartUpOptions+1
        ADD     LR, SB, #:INDEX:ParentBase
        EOR     R4, R4, #4 :SHL: 16     ;convert configured drive to internal drive numbering
        STMIA   LR, {R1,R2,R4,R6}
 [ Debug1
        DREG    R6, "Winnie sizes:"
 ]
        ; Set floppy sizes to sizes needed for extant E format floppies
        LDR     LR, =(SzNewFloppyFs/256) * &01010101
        MOV     R2, R7, ASL #3  ; Floppies*8
        RSB     R2, R2, #32     ; 32 - Floppies*8
        MOV     LR, LR, LSR R2  ; Ensures top bytes which correspond to non-existing drives get zeroed
        STR     LR, FloppySizes

        ASSERT  Create_Size = 5*4
        LDMIA   R0, {R0,R2,R4,R5,LR}    ;copy FS descriptor block from parent
        ASSERT  Create_Title=1*4        ;convert parent module offsets to absolute
        ADD     R2, R2, R1
        ASSERT  Create_BootText=2*4
        ADD     R4, R4, R1
        ASSERT  Create_LowLevel=3*4
        ADD     R5, R5, R1
        ASSERT  Create_Misc=4*4
        ADD     LR, LR, R1

        sbaddr  R1, FS_Flags
        STMIA   R1, {R0,R2,R4,R5,LR}
 [ Debug1
        DREG    R0, "Init block:",cc
        DREG    R2, " ",cc
        DREG    R4, " ",cc
        DREG    R5, " ",cc
        MOV     R0, LR
        DREG    R0, " "
 ]

;initialise critical subroutine workspace
        sbaddr  R0, CriticalStack1
        STR     R0, CriticalSP1
        sbaddr  R0, CriticalStack2
        STR     R0, CriticalSP2

;initialise most Globals
        baddr   R0, DefGlobals
        sbaddr  R1, DefGlobStart
        MOV     R2, #SzDefGlobals
        BL      BlockMove
 [ NewFs
        BL      InvalidateFragCache
 ]

;initialise Drive & disc records, ptrs to Free space Maps and defect lists
        sbaddr  R4, DrvRecs
        sbaddr  R5, DiscRecs
        ASSERT  SzDefectList=&200

        MOV     R2, #0          ;ctr
        ADD     R7, R7, #4      ;first non existent floppy Drive
10
        ; Disc record initialisation
        ASSERT  (DiscFlags :MOD: 4)=0
        ASSERT  Priority = DiscFlags+1
        ASSERT  DiscsDrv = Priority+1
        ASSERT  DiscUsage = DiscsDrv+1
        MOV     LR, #DefDiscRecEnd
        STR     LR, [R5,#DiscFlags]

        ; Initialise drive record
        MOV     LR, #Uncertain :OR: Unknown
        STRB    LR, [R4,#DrvsDisc]
        MOV     LR, #0
        STRB    LR, [R4, #DrvFlags]
        STRB    LR, [R4, #LockCount]
        STR     LR, [R4,#ChangedSeqNum]

        ; Save R2 and R3 over need for them
        Push    "R2, R3"

        ; Check that this drive exists - store a 0 for non-existant drives
        TST     R2, #4
        MOVEQ   LR, R8
        MOVNE   LR, R7
        CMP     R2, LR
        MOVHS   r2, #0
        BHS     %FT15

        ; Get size byte, skip allocation if size is 0
        ASSERT  FloppySizes = WinnieSizes+4
        sbaddr  LR, WinnieSizes
        LDRB    R2, [LR, R2]
        ADDS    R3, R2, R2, ASL #8
        BEQ     %FT15

        ; Claim the block, mapping fails to no block
        MOV     R0, #ModHandReason_Claim
 [ Debug1
        DREG    R3, "Claiming map block of size "
 ]
        BL      OnlyXOS_Module
        MOVVS   R2, #0
 [ Debug1
        DebugError "Claim error on maps:"
 ]

15
        ; Save the block's address, restore R2 and R3 and set Winnie/Floppy Size to 0 if no block
        STR     R2, [R4, #DrvsFsMap]
        MOVS    R0, R2

        Pull    "R2, R3"

        ; If stored a 0, set Winnie/FloppySize to 0
        sbaddr  LR, WinnieSizes,EQ
        STREQB  R0, [LR,R2]

20
        ; Map allocation done for this drive

        ; Move to next disc and drive
        ADD     R4, R4, #SzDrvRec
        ADD     R5, R5, #SzDiscRec
        ADD     R2, R2, #1
        CMPS    R2, #8
        BLO     %BT10

        ; Set up DefectSpace
        SUB     R3, R3, SB
        STR     R3, DefectSpace

        ; Read the Truncate CMOS bit and toggle its sence when we store it
        MOV     r0, #ReadCMOS
        MOV     r1, #FileSwitchCMOS
        SWI     XOS_Byte
        BVS     %FT85
        TST     r2, #FileSwitchTruncateNamesCMOSBit
        LDRB    lr, Flags
        ORREQ   lr, lr, #TruncateNames
        STRB    lr, Flags
 [ Debug1
        DREG    r2, "FileSwitchCMOS="
        MOV     r2, lr
        DREG    r2, "Flags="
 ]

        BL      ReadCaseTables

        ; Declare ourselves
        BL      DeclareFS       ;(R11->R0,V)
 [ Debug1
        DebugError "Declare error:"
 ]
        BVS     %FT85           ; Middle of Die code
        BL      FileCoreExit
 [ ExceptionTrap
        baddr   LR, Exception-8
        MOV     LR, LR, LSR #2
        ORR     LR, LR, #&EA000000
        MOV     R1, #0
        STR     LR, [R1]
        STR     LR, [R1,#4]
        STR     LR, [R1,#&C]
        STR     LR, [R1,#&10]
        STR     LR, [R1,#&14]
 ]
        Pull    "R7-R11,PC",,^

        LTORG

; >>>>>>>>
; DieEntry
; >>>>>>>>

DieEntry
        getSB
        TEQS    SB, #0
        MOVEQS  PC, LR                  ;if base incarnation
        Push    "R7-R11,LR"
        MOV     LR, #1
        STRB    LR, ReEntrance
        MOV     R10,#0
        MOV     R1, #8
        BL      CloseAllByDisc          ;close all ADFS files
        MOVVS   R9, R0
 [ Debug
        DebugError "CloseAll Error:"
 ]
        ; UnDeclare FS from FileSwitch
        MOV     R0, #FSControl_RemoveFS
        LDR     R1, FS_Title
        BL      OnlyXOS_FSControl
 [ Debug
        DebugError "Error from RemoveFS:"
 ]
85
        ; Reentry point from init routine above on failure to register FS with FileSwitch
        MOVVS   R9, R0

        ; Delete the parent of this incarnation (eg ADFS)
        LDR     R1, ParentBase
        LDR     R0, [R1,#Module_Title]
        ADD     R1, R1, R0
        MOV     R0, #ModHandReason_Delete
        SWI     XOS_Module

 [ NewFs
  [ Module_Version >= 205
        MOV     R4, #8          ; return all map spaces
  |
        LDRB    R4, Winnies     ;return winnie map spaces
  ]
        B       %FT94
93
        DrvRecPtr  R2,R4
        LDR     R2, [R2,#DrvsFsMap]
        BICS    R2, R2, #HiFsBits
        MOVNE   R0, #ModHandReason_Free
        BLNE    OnlyXOS_Module  ;ignore errors
94
        SUBS    R4, R4, #1
        BPL     %BT93
 ]

        BL      FileCoreExit

        ; Release message file
        LDR     R0, message_file_open
        TEQ     R0, #0
        ADRNE   R0, message_file_block
        SWINE   XMessageTrans_CloseFile ; Ignore error from this

        MOV     R0, #ModHandReason_Free
        MOV     R2, SB
        SWI     XOS_Module          ;Free workspace
 [ Debug
        DebugError "Heap error:"
 ]
95
 [ Debug
        BVC     %FT01
        DREG    R10, "Error - ",cc
        DREG    R0, "..."
01
 ]

        ORRVS   R9, R0, #ExternalErrorBit
        MOVS    R0, R9
        MOVNES  R10,R10         ;only error on init
        Pull    "R7-R11,PC",EQ,^

        BL      FindErrBlock    ;(R0->R0,V)
99
 [ Debug
        DebugError "FileCore init error:"
 ]
        Pull    "R7-R11,PC"

FSHdr
        DCD     OpenFileEntry  - org
        DCD     GetBytesEntry  - org
        DCD     PutBytesEntry  - org
        DCD     OsArgsEntry    - org
        DCD     CloseFileEntry - org
        DCD     OsFileEntry    - org
        DCD     fsinfo_flushnotify :OR: fsinfo_multifsextensions :OR: fsinfo_dontuseload :OR: fsinfo_extrainfo
        DCD     OsFunEntry     - org
        DCD     0                       ; FSExtra info

; =========
; DeclareFS
; =========

; Entry R11 ptr to private word

DeclareFS ROUT
        Push    "r0-r10,lr"
        SUB     sp, sp, #FS_size

        MOV     r0, sp
        baddr   r1, org
        baddr   r2, FSHdr

        ASSERT  FS_name=0*4
        ASSERT  FS_startuptext=1*4
        LDR     r3, FS_Title
        SUB     r3, r3, r1
        LDR     r4, FS_BootText
        SUB     r4, r4, r1
        STMIA   r0!, {r3,r4}

        ASSERT  FS_open=2*4
        ASSERT  FS_get=3*4
        ASSERT  FS_put=4*4
        ASSERT  FS_args=5*4
        ASSERT  FS_close=6*4
        ASSERT  FS_file=7*4
        LDMIA   r2!, {r3-r8}
        STMIA   r0!, {r3-r8}

        ASSERT  FS_info = 8*4
        ASSERT  FS_func=9*4
        ASSERT  FS_gbpb=10*4
        ASSERT  FS_extra=11*4
        LDMIA   r2!, {r3,r4,r6}
        LDRB    lr, FS_Id
        ORR     r3, r3, lr
        MOV     r5, #0
        STMIA   r0!, {r3,r4,r5,r6}

        MOV     r0, #FSControl_AddFS            ;declare as filing system
        SUB     r2, sp, r1
        MOV     r3, r11
        BL      OnlyXOS_FSControl
 [ Debug1
        DebugError "Error on declaring FileCore:"
 ]

        MOVVC   r0, #FSControl_AddSecondaryFS
        LDRVC   r1, FS_Title
        LDRVC   r2, ParentBase
        LDRVC   r3, ParentPrivate
        BLVC    OnlyXOS_FSControl
 [ Debug1
        DebugError "Error after declaring secondary FS:"
 ]
        ADD     sp, sp, #FS_size
        STRVS   r0, [sp]
        Pull    "r0-r10,pc"

ReadCaseTables ROUT
        Push    "lr"
        MOV     r0, #-1
        SWI     XTerritory_UpperCaseTable
        MOVVS   r0, #Nowt
        STR     r0, UpperCaseTable
        Pull    "pc",,^

; >>>>>>>>>>>>
; ServiceEntry
; >>>>>>>>>>>>

ServiceEntry ROUT
        ; Rapid service rejection
        TEQ     r1, #Service_ClaimFIQ
        TEQNE   r1, #Service_Memory
        TEQNE   r1, #Service_FSRedeclare
        TEQNE   r1, #Service_Reset
        TEQNE   r1, #Service_IdentifyDisc
        TEQNE   r1, #Service_EnumerateFormats
        TEQNE   r1, #Service_IdentifyFormat
        TEQNE   r1, #Service_DisplayFormatHelp
        TEQNE   r1, #Service_TerritoryStarted
        MOVNES  pc, lr

        ; Service entry and check for base invocation of FileCore
        Push    "R0-R2,R11,R12,LR"      ;need entry R12 stacked for FSRedeclare
        getSB
        TEQ     SB, #0
        BEQ     DoService_WithoutSB

        ; Switch amoungst the recognised services
 [ FileCache
        TEQ     r1, #Service_ClaimFIQ
        BEQ     DoService_ClaimFIQ
 ]
        TEQ     r1, #Service_Memory
        BEQ     DoService_Memory
        TEQ     r1, #Service_FSRedeclare
        BEQ     DoService_FSRedeclare
        TEQ     r1, #Service_Reset
        BEQ     DoService_Reset
        TEQ     r1, #Service_TerritoryStarted
        BEQ     DoService_TerritoryStarted
        B       DoService_PassedOn


DoService_Reset
 [ FileCache
        LDRB    R0, Interlocks
        BIC     R0, R0, #&FF :EOR: NoOpenFloppy :EOR: NoOpenWinnie
        STRB    R0, Interlocks
        LDRB    LR, MaxFileBuffers      ;IF drivers can run in background
        TEQS    LR, #0
 [ fix_4
        BEQ     %FT11

        LDR     R0, FloppyProcessBlk
        BL      %FT95
        LDR     R0, WinnieProcessBlk
 |
        BNE     %FT11

        LDRB    R0, FloppyProcessBlk
        BL      %FT95
        LDRB    R0, WinnieProcessBlk
 ]
        TSTS    R0, #ARM_CC_Mask
        BLEQ    %FT95

        LDR     LR, FirstFcb
        TSTS    LR, #ARM_CC_Mask            ;AND at least one file open
        MOVEQ   R0, #TickerV
        ADREQL  R1, TickerEntry
        MOVEQ   R2, SB                  ;restart scheduler
        SWIEQ   XOS_Claim               ;(R0,R1->R0,V)
11
 ]

 [ Module_Version < 205
        MOV     R0, #OsbyteReadResetType
        MOV     R1, #0
        MOV     R2, #-1
        SWI     XOS_Byte
        TEQS    R1,#0
        BEQ     %FT50           ;soft reset

        MOV     LR, #1                  ;DIR/NODIR on hard reset or power on
        STRB    LR, ReEntrance
        LDRB    LR, StartUpOptions
        TSTS    LR, #NoDirBit
        BNE     %FT50
        myaddr  R1, RootText
        BL      DoOsFunDir              ;(R1->R0,V)
        baddr   R1, RootLibText,VC      ;if Dir set ok try to set Lib
        BLVC    UseRootLibIfUnset       ;(R1->R0,V)
        B       %FT85

50
 ]

        LDRB    LR, ReEntrance
        TEQS    LR, #0
        BEQ     %FT90                   ;no aborted activity
        MOV     LR, #1
        STRB    LR, ReEntrance

        BL      ReturnBuffer            ;return chunks claimed for data move

        MOV     R0, #7
55                              ;make disc <-> drive mapping consistent
        DiscRecPtr  R1,R0
        MOV     LR, #0
        STRB    LR, [R1,#DiscUsage]
        LDRB    R1, [R1,#DiscsDrv]
        CMPS    R1, #8
        BHS     %FT60
        DrvRecPtr  R1,R1
        LDRB    R1, [R1,#DrvsDisc]
        BIC     R1, R1, #Uncertain
        TEQS    R1, R0
        BLNE    UnlinkByDisc
60
        DrvRecPtr  R1,R0
        LDRB    R1, [R1,#DrvsDisc]
        BIC     R1, R1, #Uncertain
        CMPS    R1, #8
        BHS     %FT65
        DiscRecPtr  R1,R1
        LDRB    R1, [R1,#DiscsDrv]
        TEQS    R1, R0
        BLNE    UnlinkByDrive
65
        SUBS    R0, R0, #1
        BPL     %BT55

 [ F
will need to finish of critical routines (write FS Map and dir etc)
 ]
85
        BL      FileCoreExit
90
        B       DoService_PassedOn

95                           ;routine to tidy up background transfer on reset
        LDRB    R1, [R0, #Process]
        TSTS    R1, #ReadAhead :OR: WriteBehind
        LDRNE   R1, [R0, #ProcessStatus]
        TSTNES  R1, #Active
        MOVNE   R1, #DataLostErr
        STRNE   R1, [R0, #ProcessError]
        LDRNE   R1, [R0, #ProcessStartPtr]
        STRNE   R1, [R0, #ProcessStatus]
        MOVS    PC, LR



 [ FileCache
DoService_ClaimFIQ
        MOV     LR, #&FF
        STRB    LR, BackgroundFiqLock
        TEQP    PC, #SVC_mode           ;enable IRQs
02                              ;wait until finished with FIQ
        LDRB    LR, FiqOwnership
        TEQS    LR, #0
        BNE     %BT02
        STRB    LR, BackgroundFiqLock
        B       DoService_PassedOn
 ]


DoService_Memory
        LDRB    R0, ScatterEntries
06
        SUBS    R0, R0, #1
        BMI     DoService_PassedOn
        sbaddr  R1, ScatterSource
        LDRB    R1, [R1,R0]
        TEQS    R1, #UseApplicArea
        BNE     %BT06
        B       DoService_Claimed


DoService_FSRedeclare
        LDR     R11,[SP,#4*4]   ;entry R12 -> private word
        BL      DeclareFS       ;(R11->R0,V)
        B       DoService_PassedOn

DoService_TerritoryStarted
        BL      ReadCaseTables
        B       DoService_PassedOn

DoService_IdentifyDisc
        ; Identify our own disc
        B       IdentifyFileCoreDisc

DoService_WithoutSB
        ; Pass around services for the base incarnation

        ; Pull regs not corrupted by non-SB services
        Pull    "r0-r2,r11"

        ; Construct return address to pass on service call location
        ADR     r12, DoService_PassedOnWithoutSB ; r12 free - no SB, remember?
        MOV     lr, pc
        AND     lr, lr, #ARM_CC_Mask
        ORR     lr, lr, r12             ; Get mode and flags too

        ; Branch off to relevant service handler routine
        TEQ     r1, #Service_EnumerateFormats
        BEQ     FileCoreService_EnumerateFormats
        TEQ     r1, #Service_IdentifyFormat
        BEQ     FileCoreService_IdentifyFormat
        TEQ     r1, #Service_DisplayFormatHelp
        BEQ     FileCoreService_DisplayFormatHelp
        TEQ     r1, #Service_IdentifyDisc
        BEQ     DoService_IdentifyDisc

DoService_PassedOnWithoutSB
        Pull    "R12,PC",,^
DoService_PassedOn
        Pull    "R0-R2,R11,R12,PC",,^
DoService_Claimed
        Pull    "R0-R2,R11,R12,LR,PC",,^

        END
