Commit a6f1b1d7 authored by Ben Avison's avatar Ben Avison

Miscellaneous improvements

Detail:
  * Added the ability for a filing system to specify to FileCore that floppy
    discs should be mounted like hard discs, to complement the existing flag
    that specifies the opposite. SDFS requires this. Ideally SCSIFS should
    start using this as well, to encapsulate boot block handling within
    FileCore.
  * Added header definitions so the FileCore and the filing systems can
    negotiate the use of a new MiscOp entry, needed as part of partitioning
    support, especially important for filing systems that use the hardware-
    specific section of the boot block, like ADFS. At present, FileCore
    doesn't do anything different (it still doesn't support partitions) but
    this enables filing systems to be modified in preparation.
  * Removed the only place where FileCore paid any attention to the
    EmptyWorks flag returned by MiscOp 1 - an obscure and not very useful
    edge case not used by any current filing systems.
  * Added 650 lines of documentation for the MiscOp SWI and low-level entry
    to the Doc directory, giving the information you need in order to
    implement a FileCore filing system.
  * Added missing header file definitions for the low-level background DiscOp
    reason code and the hot-plug drive removed flag to MiscOp 7.
  * Removed some RISC OS 2 legacy code whereby FileCore maintained its idea
    of the internal disc address of the CSD @, PSD \, Library % and URD & for
    each filing system. Since RISC OS 3.00, FileSwitch handles these
    internally and passes canonicalised paths to FileCore, so FileCore's disc
    addresses for these directories remained unset. This allows some
    considerable simplification of FileCore's path parser in particular, but
    also affects other code like that which decides how to expire disc
    records. Also note that FileCore has been unable to generate certain
    errors (like "Can't delete current directory") since RISC OS 3.00 for the
    same reason.
  * Changed loading of the map for FileCore-format discs so that the map is
    loaded into the dynamic area during the Service_IdentifyDisc handler in
    one big DiscOp rather than loading it twice, sector-by-sector, via one
    big sector cache. For one thing, the sector cache is implemented
    inefficiently - O(n^2) - and for another thing, single-sector DiscOps are
    relatively inefficient on many filing systems, especially on SD cards.
    Some example speed-ups measured for mounting discs are:
      SCSIFS,   1GB drive: was 0.62 sec, now 0.40 sec (1.55 x speedup)
      SCSIFS, 256GB drive: was 1.44 sec, now 0.52 sec (2.77 x speedup)
      SDFS,     2GB drive: was 1.25 sec, now 0.14 sec (8.93 x speedup)
Admin:
  Tested on a beagleboard, with SCSIFS and SDFS.

Version 3.50. Tagged as 'FileCore-3_50'
parent d5ce013d
This diff is collapsed.
| Copyright 2012 Castle Technology Ltd
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
|
Dir <Obey$Dir>
amu_machine debug THROWBACK=-throwback
| Copyright 2012 Castle Technology Ltd
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
|
Dir <Obey$Dir>
amu_machine gpa_debug THROWBACK=-throwback
......@@ -11,13 +11,13 @@
GBLS Module_HelpVersion
GBLS Module_ComponentName
GBLS Module_ComponentPath
Module_MajorVersion SETS "3.49"
Module_Version SETA 349
Module_MajorVersion SETS "3.50"
Module_Version SETA 350
Module_MinorVersion SETS ""
Module_Date SETS "19 Mar 2012"
Module_ApplicationDate SETS "19-Mar-12"
Module_Date SETS "14 Apr 2012"
Module_ApplicationDate SETS "14-Apr-12"
Module_ComponentName SETS "FileCore"
Module_ComponentPath SETS "castle/RiscOS/Sources/FileSys/FileCore"
Module_FullVersion SETS "3.49"
Module_HelpVersion SETS "3.49 (19 Mar 2012)"
Module_FullVersion SETS "3.50"
Module_HelpVersion SETS "3.50 (14 Apr 2012)"
END
/* (3.49)
/* (3.50)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 3.49
#define Module_MajorVersion_CMHG 3.50
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 19 Mar 2012
#define Module_Date_CMHG 14 Apr 2012
#define Module_MajorVersion "3.49"
#define Module_Version 349
#define Module_MajorVersion "3.50"
#define Module_Version 350
#define Module_MinorVersion ""
#define Module_Date "19 Mar 2012"
#define Module_Date "14 Apr 2012"
#define Module_ApplicationDate "19-Mar-12"
#define Module_ApplicationDate "14-Apr-12"
#define Module_ComponentName "FileCore"
#define Module_ComponentPath "castle/RiscOS/Sources/FileSys/FileCore"
#define Module_FullVersion "3.49"
#define Module_HelpVersion "3.49 (19 Mar 2012)"
#define Module_LibraryVersionInfo "3:49"
#define Module_FullVersion "3.50"
#define Module_HelpVersion "3.50 (14 Apr 2012)"
#define Module_LibraryVersionInfo "3:50"
......@@ -68,6 +68,8 @@ CreateFlag_FixedDiscEjects * 1:SHL:7 ; Fixed discs support MiscOp_
CreateFlag_DriveStatusWorks * 1:SHL:8 ; Drive status supported MiscOp_DriveStatus
CreateFlag_BigDiscSupport * 1:SHL:9 ; Uses sector addresses not byte addresses
CreateFlag_NewErrorSupport * 1:SHL:10 ; Errors in top bit set addresses
CreateFlag_FloppyDiscsMountLikeFixed * 1:SHL:11 ; Floppy driver only reads the boot block, FileCore validates if and sets up the disc record
CreateFlag_MiscOp8Support * 1:SHL:12 ; Filing system supports MiscOp 8
Create_Id # 1
Create_Title # 4
Create_BootText # 4
......@@ -129,6 +131,7 @@ DefectList_BigMap_End * &40000000
;
; FileCore_Features bits
Feature_NewErrors * 1:SHL:0
Feature_FloppyDiscsCanMountLikeFixed * 1:SHL:1
;
; FileCore_DiscOp and FileCore_SectorOp legacy disc addresses
......@@ -219,6 +222,7 @@ DiscOp_Op_ScatterList_Flag * 1:SHL:5
DiscOp_Op_IgnoreEscape_Flag * 1:SHL:6
DiscOp_Op_IgnoreTimeout_Flag * 1:SHL:7
DiscOp_Op_Atomic_Flag * 3:SHL:6 ; ignore both escape and timeout
DiscOp_Op_BackgroundOp_Flag * 1:SHL:8 ; internal use only
;
; FileCore_MiscOp reason codes
......@@ -243,6 +247,8 @@ MiscOp_Eject # 1
MiscOp_ReadInfo # 1
MiscOp_DriveStatus # 1 ; for checking status of a drive
MiscOp_DriveLocked_Flag * 1:SHL:0
MiscOp_DriveHidden_Flag * 1:SHL:1
MiscOp_PostMount # 1
MiscOp_FirstUnknown # 0
OPT OldOpt
......
......@@ -61,6 +61,10 @@ $name.Err * &$num
; In the interests of consistency between FileCore-based filing systems, other
; errors are mentioned in comments. This includes the BBC version of ADFS
; (although only the least-significant byte of error numbers were used there).
;
; In general, it's best to avoid using errors < &40, since these numbers can
; also be disc error numbers. On the BBC, filing system errors were supposed to
; be >= &80, and this is still evidenced below.
11 $fcerror ExtEscape, "Escape"
;70 ; "Format not available for Winnies" (ADFS)
......
......@@ -1290,6 +1290,7 @@ LenList # 0
TSTS LR, #DirBit
BEQ %FT48 ;skip if file
[ :LNOT: RO3Paths
ASSERT LibDir=UserRootDir+4 ;deal with side effects of moving dir
ASSERT CurDir=LibDir+4
ASSERT BackDir=CurDir+4
......@@ -1301,6 +1302,7 @@ LenList # 0
STREQ R2, [R0,#-4]
CMPS R0, R1
BLS %BT43
]
sbaddr R0, RootCache
MOV R1, R0
......
......@@ -75,6 +75,12 @@ ScatterListNegThresh * &10000
GBLL FixTruncateOnBigDiscs
FixTruncateOnBigDiscs SETL {TRUE}
GBLL RO3Paths
RO3Paths SETL {TRUE}
GBLL ReadMapDuringIdentify
ReadMapDuringIdentify SETL {TRUE}
GBLL Dev ; Extra code to do postmortem when things go bang
Dev SETL {FALSE}
......
......@@ -59,8 +59,6 @@ M * K*K
SzOldFs * &200
SzNewFloppyFs * &400
DiscOp_Op_BackgroundOp_Flag * 1:SHL:8 ;internal use only
DiscBits * 2_111 :SHL: (32-3) ;In all disc addresses
VerifyRetries * 5
......
......@@ -19,6 +19,8 @@
AREA |FileCore$$Code|, CODE, READONLY, PIC
ENTRY
; Module Header
Module_BaseAddr
DCD 0 ; no start entry
......@@ -97,6 +99,7 @@ TruncateNames bit 4 ; 0 means truncate, 1 means barf (yup, its the oth
message_file_open # 4 ; MessageTrans open flag
DCD 0
[ :LNOT: RO3Paths
UserRootDir # 4
DCD -1
LibDir # 4
......@@ -105,6 +108,7 @@ CurDir # 4
DCD -1
BackDir # 4
DCD -1
]
CritBufDir # 4 ; use when BufDir itself must be invalid
DCD -1
BufDir # 4 ; currently buffered directory
......
......@@ -897,10 +897,12 @@ StartupFileCoreDisc ROUT
]
[ :LNOT: ReadMapDuringIdentify
BLVC AdjustFsSpace
[ DebugL
LDRB r11, [r5, #DiscFlags]
DREG r11, "Disc flags are "
]
]
BLVC ReadFsMap
......@@ -1419,6 +1421,19 @@ FileType_FileCoreFloppyDiscStore
DLINE "new map"
]
[ ReadMapDuringIdentify ; map is already in dynamic area in this case
ASSERT BigDisc
ASSERT DynamicMaps
; Read the flag that tells us which copy of the map was loaded
LDR lr, [r4, #DrvsFsMapAddr]
ADD lr, lr, r9, LSL r7 ; Zones<<Log2SectorSize
LDR lr, [lr]
TEQ lr, #0
BICEQ r11, r11, #AltMapFlag
ORRNE r11, r11, #AltMapFlag
|
; Initialise the zone flags in the map to not valid
MOV r0, #0
BL SetAllZoneFlags
......@@ -1465,6 +1480,8 @@ FileType_FileCoreFloppyDiscStore
ORR r11, r11, #AltMapFlag
40
] ; ReadMapDuringIdentify
; Common DiscFlag settings on E disc
BIC r11, r11, #OldMapFlag :OR: OldDirFlag
......@@ -1745,10 +1762,21 @@ Mount
; Mount non-mounting winnies by reading defect list to scratch space.
; Need the defect list for heads/sectorsize/secspertrk/density/lowsector/DiscSize
; from boot block.
[ {TRUE} ; Support floppies on filing systems that can only mount via boot block
LDR lr, FS_Flags
TST r1, #bit2
TSTEQ lr, #CreateFlag_FixedDiscsMountLikeFloppy
BEQ %FT09
TST r1, #bit2
TSTNE lr, #CreateFlag_FloppyDiscsMountLikeFixed
BEQ %FT10
09
|
TST r1, #bit2
LDREQ lr, FS_Flags
TSTEQ lr, #CreateFlag_FixedDiscsMountLikeFloppy
BNE %FT10
]
MOV r2, #DefectListDiscAdd
ORR r2, r2, r1, ASL #32-3
......@@ -1772,10 +1800,21 @@ Mount
; For non-mounting winnies verify the defect list and copy/generate fields
; as appropriate.
[ {TRUE} ; Support floppies on filing systems that can only mount via boot block
LDR lr, FS_Flags
TST r1, #bit2
TSTEQ lr, #CreateFlag_FixedDiscsMountLikeFloppy
BEQ %FT12
TST r1, #bit2
TSTNE lr, #CreateFlag_FloppyDiscsMountLikeFixed
BEQ %FT20
12
|
TST r1, #bit2
LDREQ lr, FS_Flags
TSTEQ lr, #CreateFlag_FixedDiscsMountLikeFloppy
BNE %FT20
]
Push "r0,r1"
MOV r0, #ScratchSpace
......@@ -1972,11 +2011,26 @@ PollChange ROUT
ORREQ R1, R1, #Uncertain
15
[ {TRUE}
; Rationale for this change:
; * it's impossible to get here unless the FS reported Changed, so there's
; no point in testing for the NotChanged or MaybeChanged cases
; * the Unknown flag implies the Uncertain flag, and FileCore already treats
; Unknown:OR:Uncertain drives identically to Full:OR:Uncertain ones
; * for the existing drive state to be Empty implies that in an earlier poll
; the FS returned the Empty flag. No existing FS does this without the
; EmptyWorks flag as well, and EmptyWorks is a sticky flag, so it must
; still be set. Logically, this makes sense too. So removing this check
; removes the only place where FileCore examines the EmptyWorks flag,
; simplifying the API.
TSTS R1, #Empty
|
; If disc hasn't changed and the drive was unknown or empty and empty works on this drive
; and one of notchanged, maybechanged and changed are set
TSTS R1, #Unknown :OR: Empty
TSTNES R3, #MiscOp_PollChanged_EmptyWorks_Flag
TSTNES R3, #MiscOp_PollChanged_NotChanged_Flag :OR: MiscOp_PollChanged_MaybeChanged_Flag :OR: MiscOp_PollChanged_Changed_Flag
]
20
; then mark the disc as full and uncertain
MOVNE R1, #Full :OR: Uncertain
......@@ -2083,6 +2137,21 @@ FindDiscRec ROUT
CMPNES R8, #8
ADDLO R7, R7, #8 ;Higher priority for discs in a drive
[ RO3Paths
;Dont forget discs holding CritBufDir or BufDir
LDR R0, CritBufDir
CMPS R0, #-1
BEQ %FT30
CMPS R4, R0, LSR #(32-3)
BEQ %FT40 ;holds an important dir
30
LDR R0, BufDir
CMPS R0, #-1
BEQ %FT30
CMPS R4, R0, LSR #(32-3)
BEQ %FT40 ;holds an important dir
30
|
;Dont forget discs holding UserRootDir, LibDir, CurDir, BackDir, or Bufdir
MOV R8, #:INDEX:UserRootDir
ASSERT LibDir=UserRootDir+4
......@@ -2100,6 +2169,7 @@ FindDiscRec ROUT
ADD R8, R8, #4
CMPS R8, #:INDEX:BufDir
BLS %BT20
]
;dont forget floppies with open files
MOV R0, R4
......@@ -2251,6 +2321,18 @@ FreeDiscRec ROUT
DLINE ")"
]
[ RO3Paths
;Invalidate CritBufDir or BufDir if on this disc
LDR LR, CritBufDir
CMPS R0, LR, LSR #(32-3)
MOVEQ LR, #-1
STREQ LR, CritBufDir
LDR LR, BufDir
CMPS R0, LR, LSR #(32-3)
MOVEQ LR, #-1
STREQ LR, BufDir
|
;Invalidate UserRootDir,LibDir, CurDir, BackDir, or Bufdir if on this disc
MOV R1, #:INDEX:UserRootDir
ASSERT LibDir=UserRootDir+4
......@@ -2265,6 +2347,7 @@ FreeDiscRec ROUT
ADD R1, R1, #4
CMPS R1, #:INDEX:BufDir
BLS %BT10
]
BL InvalidateFragCache
BL UnCacheDisc
......
......@@ -331,6 +331,11 @@ NextChar
RSBNES LR, R0, #" "
Pull "PC"
[ RO3Paths ; these used to live inside code we've switched out
RootLibText = RootChar,".Library",0
CsdText = CsdChar,0
]
; ==========
; FullLookUp
; ==========
......@@ -368,15 +373,19 @@ FullLookUp ROUT
AND R6, R6, #C_bit ; R6<>0 <=> bit 7 set chars used
BVS %FT95
[ :LNOT: RO3Paths
LDR R3, CurDir ;Current directory is default
]
MOV R4, #0
BL SkipSpaces
TEQS R0, #DiscSpecChar
[ :LNOT: RO3Paths
BEQ %FT03
TSTS R2, #MustBeDisc
BEQ %FT05 ;if path doesn't start with disc spec
03
]
; :<disc> or MustBeDisc
; advance to start of disc name
......@@ -392,6 +401,7 @@ FullLookUp ROUT
BLCC NextChar ; skip delimiter
TEQS R0, #RootChar
BLEQ NextChar ; skip $
[ :LNOT: RO3Paths ; since RO3, FileSwitch canonicalises everything so we only need the start-with-disc case above
B %FT25
05 ;handle special dir chars
......@@ -485,6 +495,7 @@ CsdText = CsdChar,0
Pull "R1-R2"
BVS %FT95 ;error
30
] ; endif :LNOT: RO3Paths
; We now have:
; r3 = root dir of path (may be $, &, %, \, @ or $ of default drive)
BL Bit7Disc ;if bit 7 set chars used must be new format
......@@ -514,6 +525,9 @@ CsdText = CsdChar,0
35
BL FindDir ;(R3->R0,R5,R6)
BVS %FT95 ;error in getting dir
[ RO3Paths
B %FT45
|
BL ThisChar
TEQS R0, #UpChar
BNE %FT45
......@@ -521,6 +535,7 @@ CsdText = CsdChar,0
BL ToParent
; R3=disc address of parent
BL NextChar
]
40
BL ThisChar
BCS %FT60 ;last term C=1 for dir
......
......@@ -257,7 +257,7 @@ OsFileBack2
DLINE "name load exec length atts ftype result - leave MyOsFile"
DREG R1,,cc
DREG R2,,cc
; DREG R3,,cc
; DREG R3,,cc
DREG R4,,cc
DREG R5,,cc
DREG R6,,cc
......@@ -377,6 +377,7 @@ DoOsFileDelete
TEQS R2, #2 ;file type=2 <=> trying to delete directory
BNE %FT10
BL ReadIndDiscAdd ;(R3,R4->LR)
[ :LNOT: RO3Paths
LDR R0, UserRootDir
TEQS R0, LR
MOVEQ R0, #CantDelUrdErr
......@@ -392,6 +393,7 @@ DoOsFileDelete
LDR R1, BackDir ;IF deleting PSD THEN PSD := CSD
TEQS R1, LR
STREQ R0, BackDir
]
Push "R3"
MOV R3, LR
BL GetDir ;(R3->R0,R5,R6,V)
......
......@@ -1204,6 +1204,7 @@ DoSwiFeatures
|
MOV R0, #0
]
ORR R0, R0, #Feature_FloppyDiscsCanMountLikeFixed
MOV PC, LR
[ VduTrap
......
......@@ -1084,6 +1084,105 @@ SanityCheckNewMap ROUT
DLINE "Sanity checking new map"
]
[ ReadMapDuringIdentify
ASSERT BigMaps
ASSERT BigDisc
; Prior to issuing Service_IdentifyDisc, the top bits in the root directory
; disc address in the disc record are tweaked to contain the drive number
; containing the disc being identified (external numbering is used)
Push "r12"
LDR r1, [r5, #DiscRecord_Root]
EOR r1, r1, #bit31
MOV r1, r1, LSR #32-3
LDR r12, [r12]
DrvRecPtr r4, r1
BL AdjustFsSpace
Pull "r12"
BVS %FT95
LDRB r7, [r5, #DiscRecord_Log2SectorSize]
LDRB r9, [r5, #DiscRecord_NZones]
LDRB lr, [r5, #DiscRecord_BigMap_NZones2]
ADD r9, r9, lr, LSL #8
BL MapDiscAdd ;(R5,R7,R9->R2)
Push "r2"
MOV r1, #1
MOV r1, r1, LSL r7
LDR r7, [r4, #DrvsFsMapAddr]
MOV r8, #0
; Register usage:
; r1 = map block length = sector size, in bytes
; r2 = disc address of map which we are testing
; r3 -> start / end of copy of map in dynamic area
; r4 = map length in bytes / -> sector in dynamic area which we are testing
; r5 -> disc record
; r7 -> base of map dynamic area
; r8 = sector offset to copy of map which we are testing
; r9 = number of sectors in map = number of zones on disc
; r10 = CrossCheck accumulator
; r12 -> FileCore instance private word
; [sp] -> disc address of first copy of the map
10 ; Next copy of the map
MOV r3, r7
MUL r4, r9, r1
MOV r10, #0
BL SWI_SectorDiscOp_ReadSectors_Myself ;(R2-R5,R12->R2-R4,V)
BVS %FT30
MOV r4, r7
20 ; Next map block in this copy of the map
; Make a simple test on the free link
LDRB r0, [r4, #FreeLink+1]
TST r0, #&80
BEQ %FT30
; Test map block against ZoneCheck byte
MOV r0, r4
BL NewCheck ;(R0,R1->LR,Z)
BNE %FT30
; Do this sector's contribution to the cross check
LDRB r0, [r4, #CrossCheck]
EOR r10, r10, r0
; Advance to the next sector of the map
ADD r4, r4, r1
CMP r4, r3
BLO %B20
; Check the cross check
TEQ r10, #&ff
BEQ %F40
30 ; A failure has happened
; If not on first copy of map, then map is bad, so give up!
TEQ r8, #0
ADDNE sp, sp, #4 ; skip disc address on stack
SUBNE sp, sp, r1
BNE %FT85
; Try the second map copy
MOV r8, r9
B %B10
40 ; Map cross-checks OK
; Store r8 after the map, so in ReadFsMap, we know where it came from
; This will be valid memory, because the zone flags are normally stored there
STR r8, [r3]
; Now prepare for the rest of the routine - it expects
; r5 -> disc record
; r7 = disc address of the first copy of the map
; r8 = sector offset to copy of the map in use
; sp is adjusted to allocate a buffer of the size of 1 sector
Pull "r7"
SUB sp, sp, r1
| ; ReadMapDuringIdentify
LDRB r4, [r5, #DiscRecord_Log2SectorSize]
MOV lr, #1
SUB sp, sp, lr, ASL r4
......@@ -1214,6 +1313,7 @@ SanityCheckNewMap ROUT
40
; Map cross-checks OK
] ; ReadMapDuringIdentify
; Check the disc record in the first map sector against
; the disc's disc record.
......@@ -1791,9 +1891,9 @@ SWI_DiscOp_CachedReadSectors_Myself ROUT
MOV sp, r11
Pull "r1,r7-r12,pc"
; ===================================
; SWI_DiscOp_CachedReadSectors_Myself
; ===================================
; =========================================
; SWI_SectorDiscOp_CachedReadSectors_Myself
; =========================================
;
; In
; r2-r4 DiscOp parameters
......@@ -1844,4 +1944,58 @@ SWI_SectorDiscOp_CachedReadSectors_Myself ROUT
MOV sp, r11
Pull "r1,r7-r12,pc"
[ ReadMapDuringIdentify
; ===================================
; SWI_SectorDiscOp_ReadSectors_Myself
; ===================================
;
; In
; r2-r4 DiscOp parameters
; r5 = disc record
; r12 = private workspace pointer
;
; Out
; r12 = unchanged
; results of DiscOp
;
SWI_SectorDiscOp_ReadSectors_Myself ROUT
Push "r1,r7-r12,lr"
[ Debug2 :LOR: Debug2D
DREG r1, "SectorDiscOpMyself(",cc
DREG r2, ",",cc
DREG r3, ",",cc
DREG r4, ",",cc
DLINE ")"
]
MOV r11, sp
LDRB lr, [r5, #DiscRecord_Log2SectorSize]
MOV r1, r2, LSR #29
BIC r2, r2, #DiscBits
RSB r8, lr, #32
MOV r7, r2, LSL lr
MOV lr, r2, LSR r8
Push "r1,r7,lr"
MOV r8, r12
MOV r2, sp
MOV r1, #DiscOp_ReadSecs :OR: DiscOp_Op_IgnoreEscape_Flag
SWI XFileCore_DiscOp64
[ DebugL
BVC %FT01
ADD r0, r0, #4
DSTRING r0, "Read sector error:"
SUB r0, r0, #4
01
]
LDRB lr, [r5, #DiscRecord_Log2SectorSize]