BigDirCode 79.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
; Copyright 1997 Acorn Computers 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.
;
; BigDirCode

        TTL     "Big directory support code"
 [ BigDir

; ==========
; TestBigDir
; ==========

; test for long filenames on this disc

; entry: R3=disc address

; exit  Z=1 <=> big directories, C,V preserved, LR->disc rec

TestBigDir ROUT
        Push    "R0,LR"
        BL      DiscAddToRec            ;(R3->LR)
33
        LDRB    R0, [LR,#DiscRecord_BigDir_DiscVersion]
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
        TEQS    R0, #1
 [ DebugX :LAND: {FALSE}
        BNE     %FT01
        DLINE   " big dir ",cc
        B       %FT02
01
        DLINE   " not big dir ",cc
02
 ]
        Pull    "R0,PC"

; =======================
; SanityCheckBigDirHeader
; =======================

; checks that a big directory's header is acceptable.

; used by FindDir to ensure that a directory seems ok-ish
; before going any further, to avoid nasty crash-type
; situations caused by stupid values appearing.

; checks:

; 1) that BigDirStartName is correct
; 2) that BigDirVersion is 0
; 3) that the size of the directory is a multiple of NewDirSize

; any other checks are left until the entire directory is read

; entry:

;   R5 points to the directory's header

; exit:

;   if error, R0 result, V set

SBProven
 = "SBPr"
 = "oven"


SanityCheckBigDirHeader ROUT
        Push    "R0,R1,LR"

 [ DebugX
        DLINE   ">SanityCheckBigDirHeader"
 ]

 [ DebugXd
84 85
        ADD     lr, r5, #BigDirName
        DSTRING lr, "sanity check; name: "
86 87 88 89 90 91 92 93 94 95 96 97
 ]

        LDR     r1, SBProven                    ; get "SBPr"
        LDR     lr, [r5, #BigDirStartName]      ; and get StarName from Dir
        TEQS    r1,lr                           ; is it broke?
 [ DebugX
        BEQ     %FT01
        DLINE   "Failed at BigDirStartMasSeq"
01
 ]
        BNE     %FT95

98 99 100
        ASSERT  (BigDirVersion:MOD:4)=1
        LDR     lr, [r5, #BigDirVersion-1]
        BICS    lr, lr, #255
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242

 [ DebugX
        BEQ     %FT01
        DLINE   "Failed at BigDirVersion"
01
 ]
        BNE     %FT95

        LDR     lr, [r5, #BigDirSize]
        MOVS    r1, lr, LSL #21         ; bottom 11 bits must be clear

 [ DebugX
        BEQ     %FT01
        DLINE   "Failed at BigDirSize not multiple of 2048"
01
 ]
        BNE     %FT95

        MOVS    r1, lr, LSR #22

 [ DebugX
        BEQ     %FT01
        DLINE   "Failed at BigDirSize too large"
01
 ]

95
        MOVNE   R0, #BrokenDirErr
        MOVEQ   R0, #0
        BL      SetVOnR0
        STRVS   R0, [SP]
 [ DebugX
        DLINE   "<SanityCheckBigDirHeader"
 ]
        Pull    "R0,R1,PC"

; ===========
; CheckBigDir
; ===========

; Check dir is well formed

; entry: R3=dir disc add, R5->dir start, R6->dir end, R10 0 -> don't check the check
; bytes, R10=1-> do check it

; exit:  IF error V set, R0 result

CheckBigDir ROUT
        Push    "R0,R1,R10,R11,LR"
 [ DebugX
        DLINE   ">CheckBigDir"
 ]

 [ DebugX
        LDR     R1, [R5, #BigDirNameLen]
        DREG    R1, "dir's name length is:"
 ]

        baddr   R1, SBProven
        LDMIA   R1, {R1, R11}

        LDR     LR, [R5, #BigDirStartName]

        TEQS    LR, R1                          ; is the StartName Ok?

 [ DebugX
        BEQ     %FT01
        DLINE   "Failed at SBPr"
01
 ]
        LDREQB  R0, [R5,#BigDirStartMasSeq]
        LDREQB  LR, [R6,#BigDirEndMasSeq]
        TEQS    R0, LR

 [ DebugX
        BEQ     %FT01
        DLINE   "Failed at sequences"
01
 ]
        LDREQ   LR, [R6, #BigDirEndName]
        TEQEQS  LR, R11

 [ DebugX
        BEQ     %FT01
        DLINE   "Failed at endname"
        DREG    LR, "End name read was:"
01
 ]
        MOV     R0, #0
        BNE     %FT90

        MOVS    R10,R10                 ;quick flag
        BLNE    TestDirCheckByte        ;(R3,R5,R6->LR,Z)

90
        BEQ     %FT95
 [ DebugX
        DLINE   "Big dir broken"
 ]
        MOV     R0, #BrokenDirErr
        LDR     LR, BufDir
        TEQS    LR, R3
        BLEQ    InvalidateBufDir
        BEQ     %FT95
        BL      TryCache                ;(R3->R11,V)
        BLVC    InvalidateDirCache      ;if a dir in cache is broken, scrap whole cache
95
        BL      SetVOnR0
        STRVS   R0, [SP]

 [ DebugX
        DLINE   "<CheckBigDir"
 ]
        Pull    "R0,R1,R10,R11,PC"

; ===================
; TestBigDirCheckByte
; ===================

; entry
;  R3 ind disc add of dir
;  R5 -> dir start
;  R6 -> dir end

; exit
;  LR check byte
;  Z  set if matches existing byte

TestBigDirCheckByte     ROUT
        Push    "R0-R2,R5,R7,LR"

 [ DebugX
        DLINE   ">TestBigDirCheckByte"
        DREG    R5, "dir at:"
 ]

; first, work out the size of the first area to accumulate

        MOV     R2,#0   ; zero the acc.

        LDR     R0, [R5, #BigDirNameLen]

243
        ADD     R0, R0, #4
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581
        BIC     R0, R0, #3                      ; name len

        LDR     R1, [R5, #BigDirEntries]        ; number of entries

 [ BigDirFix
        ASSERT  BigDirEntrySize=28

        RSB     R1, R1, R1, LSL #3              ; *7
        ADD     R0, R0, R1, LSL #2              ; 7*4=28
 |
        ASSERT  BigDirEntrySize=32

        ADD     R0, R0, R1, LSL #5              ; 32 bytes per entry
 ]

        LDR     R1, [R5,#BigDirNamesSize]       ; size of the heap of names

        ADD     R0, R0, R1

        ADD     R0, R0, #BigDirHeaderSize

 [ DebugX
        DREG    R0, "bytes to check:"
 ]

        ADD     R0, R0, R5                      ; now R0 points to first word after names

10
        LDR     LR, [R5], #4
        EOR     R2, LR, R2, ROR #13
        TEQS    R5, R0
        BNE     %BT10

; now the tail
        ADD     R5, R6, #BigDirEndName
        LDR     LR, [R5], #4
        EOR     R2, LR, R2, ROR #13
        SUB     R0, R6, #1

        ASSERT  BigDirCheckByte=-1

20
        LDRB    LR, [R5], #1
        EOR     R2, LR, R2, ROR #13
        TEQS    R5, R0
        BNE     %BT20

        EOR     R2, R2, R2, LSR #16     ;reduce to 8 bits
        EOR     R2, R2, R2, LSR #8
        AND     R2, R2, #&FF

        LDRB    LR, [R6,#BigDirCheckByte]
        TEQS    R2, LR
 [ DebugX
        DREG    LR, "check byte"
        DREG    R2, "value:"
 ]
        MOV     LR, R2

 [ DebugX
        DLINE   "<TestBigDirCheckByte"
 ]

        Pull    "R0-R2,R5,R7,PC"

; =================
; ReadBigDirEntries
; =================

; entry:

; R3 indirect disc addr of dir
; R5 pointer to big dir
; R7 buffer ptr
; R8 number of names to transfer
; R9 offset in dir
; R10 buffer end
; R11 fsfunc reason code

; exit:

; R5=number of names transferred
; R9=new offset

; all other regs may be corrupted except R12, R13

; while running;

; R4=pointer to current entry

ReadBigDirEntries       ROUT
        Push    "R0,R1,R2,R9,lr"
 [ DebugX
        DLINE   ">ReadBigDirEntries"
 ]
        LDR     r1, [r5, #BigDirEntries]        ; get the number of entries in the dir
 [ DebugX
        DREG    r1, "dir entries:"
        DREG    r9, "index value:"
 ]
        CMP     r9, r1                  ; check if offset too large
        MOVHS   r9, #-1
        MOVHS   R5, #0
        BHS     %FT95                   ; nothing transferred

; this still to be implemented!

; common set-up code

        BL      GetDirFirstEntry        ; (R3,R5->R4)

 [ BigDirFix
        ASSERT  BigDirEntrySize=28
        RSB     LR, R9, R9, LSL #3      ; *7
        ADD     R4, R4, LR, LSL #2      ; 7*4=28
 |
        ASSERT  BigDirEntrySize=32
        ADD     R4, R4, R9, LSL #5      ; pointer to current entry
 ]

        TEQS    R11, #fsfunc_ReadDirEntriesInfo
        BEQ     %FT20

        TEQS    R11, #fsfunc_ReadDirEntries
        BEQ     %FT40

        TEQS    R11, #fsfunc_CatalogObjects
        BEQ     %FT60

        B       %FT95

20
        ADD     R7, R7, #3      ; word align it
        BIC     R7, R7, #3
        SUB     LR, R10, R7
        LDR     R0, [R4, #BigDirObNameLen]
 [ DebugX
        DREG    R0, "name length:"
 ]
        ADD     R0, R0, #&15+3
        BIC     R0, R0, #3
        CMPS    R0, LR                  ; space for entry?
 [ DebugX
        DREG    LR, "space in buffer:"
        DREG    R0, "space for entry:"
        BLS     %FT01
        DLINE   "Buffer overflowed"
01
 ]
        BHI     %FT25                   ; no space!

; have space for entry
        BL      ReadIntAtts     ;(R3,R4->LR)
        TSTS    LR, #DirBit
        MOVEQ   R0, #1
        MOVNE   R0, #2
        BL      ReadLoad        ;(R3,R4->LR)
        STR     LR, [R7],#4
        BL      ReadExec        ;(R4->LR)
        STR     LR, [R7],#4
        BL      ReadLen         ;(R3,R4->LR)
        STR     LR, [R7],#4
        BL      ReadExtAtts     ;(R3,R4->LR)
        STR     LR, [R7],#4
        STR     R0, [R7],#4     ;atts

        LDR     R6, [R4, #BigDirObNameLen]
        Push    "R4"
        BL      GetBigDirName   ;(R5,R6->LR)
        MOV     R4, LR
 [ DebugX :LOR: DebugXd
        DSTRING R4, "name:"
 ]
        BL      PutStringToBuf  ;write the string to the buffer
        Pull    "R4"
        BLCC    Put0ToBuf

        BCS     %FT25           ; buffer full

        ADD     R9, R9, #1
        ADD     R4, R4, #BigDirEntrySize
        BL      BigDirFinished
        BEQ     %FT30

        SUBS    R8, R8, #1
        BGT     %BT20

; finished count of entries to extract, but not finished dir

25
; here when buffer full or nothing left to do
        LDR     R8, [sp, #3*4]          ; old offset in dir
        SUB     R5, R9, R8              ; number of names transferred
        B       %FT95                   ; and exit

30
; end of dir
        LDR     R8, [sp, #3*4]          ; old offset in dir
        SUBS    R5, R9, R8              ; number of names transferred
        MOVEQ   R9, #-1                 ; finished
        B       %FT95                   ; and exit

40
        SUB     LR, R10, R7
        LDR     R0, [R4, #BigDirObNameLen]
        ADD     R0, R0, #1
        CMPS    R0, LR                  ; space for entry?
 [ DebugX
        BLS     %FT01
        DLINE   "Buffer overflowed"
01
 ]
        BHI     %FT45                   ; no space!

        LDR     R6, [R4, #BigDirObNameLen]
        Push    "R4"
        BL      GetBigDirName   ;(R5,R6->LR)
        MOV     R4, LR
 [ DebugX :LOR: DebugXd
        DSTRING R4, "name:"
 ]
        BL      PutStringToBuf  ;write the string to the buffer
        Pull    "R4"
        BLCC    Put0ToBuf

        BCS     %FT45           ; buffer full

        ADD     R9, R9, #1
        ADD     R4, R4, #BigDirEntrySize
        BL      BigDirFinished
        BEQ     %FT50

        SUBS    R8, R8, #1
        BGT     %BT40

; finished count of entries to extract, but not finished dir

45
; here when buffer full or nothing left to do
        LDR     R8, [sp, #3*4]          ; old offset in dir
        SUB     R5, R9, R8              ; number of names transferred
        B       %FT95                   ; and exit

50
; end of dir
        LDR     R8, [sp, #3*4]          ; old offset in dir
        SUBS    R5, R9, R8              ; number of names transferred
        MOVEQ   R9, #-1                 ; finished
        B       %FT95                   ; and exit


60 ; CatalogObjects
        ADD     R7, R7, #3      ; word align it
        BIC     R7, R7, #3
        SUB     LR, R10, R7
        LDR     R0, [R4, #BigDirObNameLen]
 [ DebugX
        DREG    R0, "name length:"
 ]
        ADD     R0, R0, #&1E+3
        BIC     R0, R0, #3
        CMPS    R0, LR                  ; space for entry?
 [ DebugX
        DREG    LR, "space in buffer:"
        DREG    R0, "space for entry:"
        BLS     %FT01
        DLINE   "Buffer overflowed"
01
 ]
        BHI     %FT65                   ; no space!

; have space for entry
        BL      ReadIntAtts     ;(R3,R4->LR)
        TSTS    LR, #DirBit
        MOVEQ   R0, #1
        MOVNE   R0, #2
        BL      ReadLoad        ;(R3,R4->LR)
        STR     LR, [R7],#4
        CMNS    LR, #1 :SHL: 20 ;C=1 <=> stamped
        ANDCS   R1, LR, #&FF
        MOVCC   R1, #0
        BL      ReadExec        ;(R4->LR)
        MOVCS   R2, LR
        MOVCC   R2, #0
        STR     LR, [R7],#4
        BL      ReadLen         ;(R3,R4->LR)
        STR     LR, [R7],#4
        BL      ReadExtAtts     ;(R3,R4->LR)
        STR     LR, [R7],#4
        STR     R0, [R7],#4     ;atts
        BL      ReadIndDiscAdd  ;(R3,R4->LR)
        BIC     LR, LR, #DiscBits
        STR     LR, [R7], #4
        STR     R2, [R7], #4
        STRB    R1, [R7], #1

        LDR     R6, [R4, #BigDirObNameLen]
        Push    "R4"
        BL      GetBigDirName   ;(R5,R6->LR)
        MOV     R4, LR
 [ DebugX :LOR: DebugXd
        DSTRING R4, "name:"
 ]
        BL      PutStringToBuf  ;write the string to the buffer
        Pull    "R4"
        BLCC    Put0ToBuf

        BCS     %FT65           ; buffer full

        ADD     R9, R9, #1
        ADD     R4, R4, #BigDirEntrySize
        BL      BigDirFinished
        BEQ     %FT70

        SUBS    R8, R8, #1
        BGT     %BT60

; finished count of entries to extract, but not finished dir

65
; here when buffer full or nothing left to do
        LDR     R8, [sp, #3*4]          ; old offset in dir
        SUB     R5, R9, R8              ; number of names transferred
        B       %FT95                   ; and exit

70
; end of dir
        LDR     R8, [sp, #3*4]          ; old offset in dir
        SUBS    R5, R9, R8              ; number of names transferred
        MOVEQ   R9, #-1                 ; finished
        B       %FT95                   ; and exit


95
        STR     r9, [sp,#3*4]
 [ DebugX
        DLINE   "<ReadBigDirEntries"
 ]
582
        Pull    "r0,r1,r2,r9,pc"
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643


; ==============
; BigDirFinished
; ==============

; entry:

; R5=pointer to dir
; R4=dir entry ptr

; exit:

; EQ if entry is beyond end of entries, LR=entries in dir

BigDirFinished ROUT
        Push    "R4,R6,LR"
 [ DebugX :LAND: {FALSE}
        DLINE   ">BigDirFinished"
        DREG    R5, "dir at:"
        DREG    R4, "entry at:"
 ]
        LDR     R6, [R5, #BigDirNameLen]
        ADD     R6, R6, #4
        BIC     R6, R6, #3

        LDR     LR, [R5, #BigDirEntries]

 [ BigDirFix
        ASSERT  BigDirEntrySize=28
        ADD     R6, R6, LR, LSL #5      ; *32
        SUB     R6, R6, LR, LSL #2      ; *(32-4)=*28
 |
        ASSERT  BigDirEntrySize=32
        ADD     R6, R6, LR, LSL #5
 ]

        ADD     R6, R6, R5
        ADD     R6, R6, #BigDirHeaderSize       ; now points to header

 [ DebugX
        DREG    R6, "end of entries:"
 ]
        CMPS    R4, R6
        MOVHI   R4, R6
        TEQS    R4, R6

        Pull    "R4,R6,PC"

; =============
; GetBigDirName
; =============

; entry: R5=dir start, R4=pointer to entry

; exit: LR=pointer to name (NOT header)

; if entry is after end of entries, returns pointer to what would
; be name after name heap

GetBigDirName ROUT
644 645
        Push    "R5,R6,R7,R8,LR"
        SavePSR R8
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673

        BL      BigDirFinished                  ; is it finished
        LDREQ   R7, [R5, #BigDirNamesSize]      ; size of names heap

        LDR     LR, [R5, #BigDirNameLen]
        LDR     R6, [R5, #BigDirEntries]
        ADD     LR, LR, #4
        BIC     LR, LR, #3
        ADD     R5, R5, LR
        ADD     R5, R5, #BigDirHeaderSize

; R5 now points at entries

 [ BigDirFix
        ASSERT  BigDirEntrySize=28
        RSB     LR, R6, R6, LSL #3
        ADD     R6, R5, LR, LSL #2
 |
        ASSERT  BigDirEntrySize=32

        ADD     R6, R5, R6, LSL #5              ; name heap
 ]

        LDRNE   R5, [R4, #BigDirObNamePtr]      ; offset into name heap
        ADDNE   LR, R5, R6
        ADDEQ   LR, R7, R6                      ; end of name heap

; [ DebugXd
674
;       DREG    LR, "name ptr:"
675 676
; ]

677 678
        RestPSR R8,,f
        Pull    "R5,R6,R7,R8,PC"
679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707

; =================
; ReadBigDirIntAtts
; =================

; entry: R3=disc address of dir
;        R4=index of entry in dir
;        R5=start of dir

; exit:  LR=atts

ReadBigDirIntAtts ROUT
        Push    "LR"
        ADD     LR, LR, R4, LSL #5              ; entry

        LDRB    LR, [R4, #BigDirAtts]           ; read the bottom 8 bits of atts

 [ DebugX
        DREG    LR, " ", cc
        DLINE   "=Big Atts"
 ]
        TSTS    LR, #DirBit
 [ FullAtts
        ASSERT  IntAttMask = &FF
 |
        ANDEQ   LR, LR, #IntAttMask
 ]
        ANDNE   LR, LR, #IntDirAttMask

708
        Pull    "PC"
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724

 [ BinaryChop
; =========
; WildCheck
; =========

; check if wild card spec term has any wild cards

; entry:
;  R1   -> term, terminated by control codes, delete, space or delimiter

; exit:  EQ -> is wild card
;        NE -> no wild card

WildCheck ROUT
 [ DebugXb
725 726
        DREG    r1, "WildCheck(wild=",cc
        DLINE   ")"
727 728
 ]

729
        Push    "R0, R1, LR"
730

731
        SUB     R1, R1, #1      ; get to just before term (NextChar skips one)
732
10
733 734 735 736
        BL      NextChar        ; get next wild character
        BCS     %FT20
        TEQS    R0, #DelimChar
        BEQ     %FT20
737

738 739 740
        TEQS    R0, #OneWildChar        ; is this a wildcard?
        TEQNES  R0, #MultiWildChar
        BNE     %BT10
741 742 743

; here when found a wild ard
 [ DebugXb
744
        DLINE   "wildcard found"
745
 ]
746
        Pull    "R0, R1, PC"
747 748 749

20
; here when reched end; need to exit NE
750
        MOVS    R0, #1
751 752

 [ DebugXb
753
        DLINE   "no wildcard"
754 755
 ]

756
        Pull    "R0, R1, PC"
757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792
 ]


; ============
; LookUpBigDir
; ============

; look up wild card spec term in dir

; entry:
;  R1   -> term, terminated by control codes ,delete ,space or delimiter
;  R2   name restriction bits, only 'must be file' and 'must be dir' apply
;  R3   disc address of dir
;  R4   -> entry in dir to start at (or following entry if C=1)
;  R5   pointer to start of dir

; exit:

; IF found R4=index of entry in dir, Z=1 <=> file, C=0
; ELSE     R4->next alphabetical entry, C=1

LookUpBigDir    ROUT
 [ DebugX
        DREG    r1,"LookUpBigDir(wild=",cc
        DREG    r2,",restrict=",cc
        DREG    r3,",dir=",cc
        DREG    r4,",index ",cc
        DREG    r5,",dir start ",cc
        DLINE   ")",cc
 ]
        Push    "r7,LR"

        SUBCC   r4,r4,#BigDirEntrySize  ; caller asked to start at this entry
        MOV     R7, #0

 [ BinaryChop
793 794
        BL      WildCheck               ; is it wildcarded?
        BNE     %FT99                   ; no!
795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
 ]
10
        ADD     r4,r4,#BigDirEntrySize
        BL      BigDirFinished          ; (R4,R5->eq->dir finished)
        BNE     %FT11

        ; end of dir
        TEQ     r7, #0
        MOVNE   r4, r7
        SEC
        B       %FT90                   ; carry already set

11
        Push    "R4,R5,R6"
        LDR     R6, [R4, #BigDirObNameLen]
        BL      GetBigDirName           ; get the name's address (in LR)
        MOV     R4, LR
        MOV     r5, #&ff                ; mask is ff
        BL      BigLexEqv               ; (R1,R4,R5->LO/EQ/HI)
        Pull    "R4,R5,R6"

        BCC     %BT10                   ;if mismatch and name<wild try next
        BEQ     %FT15                   ;EQ=>match

12
        ;mismatch and name >wild done
        TEQ     r7, #0                  ; doesn't affect C
        MOVEQ   r7, r4
        BCS     %BT10

        ; completion in the not found case

        MOV     r4, r7
        SEC                             ; set carry (not found)
        B       %FT90

15
        ; Match, but...
        BL      ReadBigDirIntAtts       ; read the attributes

;LR=Atts
        TSTS    LR, #DirBit
        BNE     %FT20                   ; found a dir
;found a file

        TSTS    R2, #MustBeDir
        BNE     %BT10
;fall through next few instructions as EQ
20
        TSTNES  R2, #MustBeFile
        BNE     %BT10

        TSTS    LR, #DirBit :SHL: 2,2 ;restore Z=1 <=> file, C=0
90
 [ Debug6
        DREG    r4,"->(entry=",cc
        BCC     %FT01
        DLINE   ",not found)"
        B       %FT02
01
        BNE     %FT01
        DLINE   " file ",cc
01
        DLINE   ",found)"
02
 ]
95
        Pull    "R7,PC"

 [ BinaryChop
99
; name was not wildcarded; we can binary chop it!

; register allocation.

; r8 = offset of entry of interest
; r9 = number of entries in range being considered
; r4 = ptr to current entry being examined
; r5 = start of dir

875
        Push    "r8, r9"
876

877
        ADD     r4, r4, #BigDirEntrySize
878 879

; first, work out offset of r4 in dir
880 881
        MOV     r8, r4                          ; R4 = size of an entry
        BL      GetDirFirstEntry                ; (R3,R5->R4)
882

883
        SUB     lr, r8, r4                      ; offset in bytes between start entry and thing
884

885
        MOV     r9, #BigDirEntrySize            ; size of a dir entry
886 887

 [ DebugX
888 889 890 891
        DREG    r8, "r8 : "
        DREG    lr, "lr : "
        DREG    r9, "r9 : "
        DREG    r4, "r4 : "
892 893
 ]

894
        DivRem  r8, lr, r9, r4                  ; r8 = offset into dir
895 896

 [ DebugXb
897
        DREG    r8, "init offset: "
898 899
 ]

900 901
        LDR     r9, [r5, #BigDirEntries]        ; number of entries in the dir
        SUB     r9, r9, r8                      ; difference
902 903

 [ DebugXb
904
        DREG    r9, "init range: "
905 906
 ]

907 908
        CMPS    r9, #0
        BNE     %FT05
909

910
        ; not found
911

912 913
        BL      GetDirFirstEntry                ; (R3,R5->R4)
        ASSERT  BigDirEntrySize=28
914 915 916 917

        RSB     R8, R8, R8, LSL #3              ; *7
        ADD     R4, R4, R8, LSL #2              ; 7*4=28

918
        SEC
919

920
        Pull    "r8, r9"
921

922
        B       %BT90
923 924 925 926 927

05

; here we have to check the middle item in the

928
;       ADD     lr, r9, #1
929
 [ DebugXb
930 931
        DREG    r8, "start: "
        DREG    r9, "len: "
932
 ]
933
        ADD     r8, r8, r9, LSR #1              ; r8 <- offset of entry to look into
934

935 936
        BL      GetDirFirstEntry                ; (R3,R5->R4)
        ASSERT  BigDirEntrySize=28
937 938 939 940 941 942 943 944 945 946 947 948 949 950

        RSB     LR, R8, R8, LSL #3              ; *7
        ADD     R4, R4, LR, LSL #2              ; 7*4=28

; now R4->entry of interest

        Push    "R4,R5,R6"
        LDR     R6, [R4, #BigDirObNameLen]
        BL      GetBigDirName           ; get the name's address (in LR)
        MOV     R4, LR
        MOV     r5, #&ff                ; mask is ff
        BL      BigLexEqv               ; (R1,R4,R5->LO/EQ/HI)
        Pull    "R4,R5,R6"

951
        BEQ     %FT80                   ; name=wild
952

953
        BCC     %FT20                   ; name<wild
954

955 956
        CMPS    r9, #1
        BEQ     %FT75
957 958 959

; name>wild.  range becomes below r8
 [ DebugXb
960
        DLINE   "name>wild"
961
 ]
962 963 964
        SUB     r8, r8, r9, LSR #1
        MOV     r9, r9, LSR #1
        B       %BT05
965 966 967

20
 [ DebugXb
968
        DLINE   "name<wild"
969
 ]
970 971
        CMPS    r9, #1
        BEQ     %FT70
972
; name<wild.  range becomes above r8
973 974 975 976
        ADD     r8, r8, #1
        SUB     r9, r9, #1
        MOVS    r9, r9, LSR #1
        BNE     %BT05                   ; if it's zero then it's not found
977 978 979


70
980 981
        ; not found
        ADD     R4, R4, #BigDirEntrySize
982
75
983 984 985
        SEC
        Pull    "R8, R9"
        B       %BT90
986 987 988 989 990


80
        ; Match, but...
 [ DebugXb
991
        DLINE   "Match, but..."
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
 ]
        BL      ReadBigDirIntAtts       ; read the attributes

;LR=Atts
        TSTS    LR, #DirBit
        BNE     %FT85                   ; found a dir
;found a file

        TSTS    R2, #MustBeDir
        BNE     %BT70
;fall through next few instructions as EQ
85
        TSTNES  R2, #MustBeFile
        BNE     %BT70

        TSTS    LR, #DirBit :SHL: 2,2 ;restore Z=1 <=> file, C=0

1009
        Pull    "R8, R9"
1010

1011
        B       %BT90
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029


 ]

; ================
; GetDirFirstEntry
; ================

; entry:

; R3 = dir ind disc address
; R5 = dir start

; exit:

; R4 points to first entry

GetDirFirstEntry ROUT
1030 1031
        Push    "R6,LR"
        SavePSR R6
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043

        BL      TestBigDir

        BNE     %FT01                           ; not a big dir

        LDR     LR, [R5, #BigDirNameLen]
        ADD     LR, LR, #4
        BIC     LR, LR, #3

        ADD     R4, R5, LR
        ADD     R4, R4, #BigDirHeaderSize

1044 1045
        RestPSR R6,,f
        Pull    "R6,PC"
1046 1047
01
        ADD     R4,R5,#DirFirstEntry            ; not a big dir
1048 1049
        RestPSR R6,,f
        Pull    "R6,PC"
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069

; ============
; NextDirEntry
; ============

; entry:

; R3=ind disc add
; R4->dir entry

; exit: r4->next dir entry

NextDirEntry ROUT
        Push    "LR"

        BL      TestBigDir
        ADDEQ   R4, R4, #BigDirEntrySize
        ASSERT  NewDirEntrySz=OldDirEntrySz
        ADDNE   R4,R4,#NewDirEntrySz

1070
        Pull    "PC"
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107

; ===============
; BigDirFreeSpace
; ===============

; entry:

; R5 -> dir start

; exit:

; LR number of bytes of unused space in the directory (always a word multiple)

BigDirFreeSpace ROUT
        Push    "R0,LR"

 [ DebugX
        DLINE   ">BigDirFreeSpace"
 ]
        LDR     R0, [R5, #BigDirSize]           ; size of the directory
        SUB     R0, R0, #BigDirHeaderSize + BigDirTailSize
        LDR     LR, [R5, #BigDirEntries]

 [ BigDirFix
        ASSERT  BigDirEntrySize=28
  [ BigDirFullBackup
        RSB     LR, LR, LR, LSL #3              ; *7
        SUB     R0, R0, LR, LSL #3              ; *7*8=56
  |
        SUB     R0, R0, LR, LSL #5              ; *32
  ]
 |
        ASSERT  BigDirEntrySize=32
  [ BigDirFullBackup
        SUB     R0, R0, LR, LSL #6              ; TWO copies of entries
  |
        SUB     R0, R0, LR, LSL #5
1108
        SUB     R0, R0, LR, LSL #2              ; *36
1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122
  ]
 ]

        LDR     LR, [R5, #BigDirNameLen]        ; length of dir name
        ADD     LR, LR, #4
        BIC     LR, LR, #3
        SUB     R0, R0, LR

        LDR     LR, [R5, #BigDirNamesSize]      ; size of the names heap
        SUB     LR, R0, LR                      ; now LR is the number of free bytes in the dir

 [ DebugX
        DREG    LR, "<BigDirFreeSpace"
 ]
1123
        Pull    "R0, PC"
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161

; ============
; IsBigDirFull
; ============

; entry:

; R1 -> last term of name
; R3 top 3 bits disc id
; R5 -> dir start

; exit:
;   IF full, V set, R0 result

; number of bytes free in a big dir is:

; size of dir - (header size + tail size) - (size for all entries) - size of name heap

IsBigDirFull ROUT
        Push    "R0,R1,R2,R6,LR"

        BL      BigDirFreeSpace                 ; (R5->LR)
        MOV     R6, LR
        ; now get the number of bytes needed for the new entry:

        MOV     R2, R1                          ; keep start of term

        BL      SkipTerm                        ; (R1->R0,R1)

        SUB     R0, R1, R2                      ; length of term

        ADD     R0, R0, #4
        BIC     R0, R0, #3

 [ BigDirFullBackup
        ADD     R0, R0, #BigDirEntrySize*2
 |
        ADD     R0, R0, #BigDirEntrySize
1162
        ADD     R0, R0, #4
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
 ]

 [ DebugX
        DREG    R0, "size needed:"
        DREG    R6, "size available:"
 ]
        CMPS    R0, R6
        MOVHI   R0, #DirFullErr
        MOVLS   R0, #0
        BL      SetVOnR0
        STRVS   R0, [SP]

        Pull    "R0,R1,R2,R6,PC"

; ===============
; MakeBigDirSpace
; ===============

; make space for a new entry in RAM copy of a directory
; ASSUMES DIR IS NOT FULL can check this with IsDirFull

; entry:

;  R1->term
;  R3 ind disc address
;  R4 -> entry
;  R5 -> dir start
;  R6 -> dir end

MakeBigDirSpace ROUT
        Push    "R0-R11,LR"
1194
        SavePSR R11
1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300

 [ DebugX
;       BL      DumpBigDir
 ]

        MOV     R2, R1
        BL      SkipTerm                ; (R1->R0,R1)
        SUB     R8, R1, R2              ; R8 = term length
        ADD     R6, R8, #4
        BIC     R6, R6, #3              ; R6 = extra required in name heap

; now we can find the entry in the name heap, and bump everything up

        BL      GetBigDirName           ; (R4,R5->LR)

; LR = name heap entry
        MOV     R0, LR                  ; source for block move
        ADD     R1, R0, R6
        ADD     R1, R1, #BigDirEntrySize ; dest for block move

; length for move
        LDR     R2, [R5, #BigDirNameLen];length of dir name
        ADD     R2, R2, #4+BigDirHeaderSize
        BIC     R2, R2, #3
        LDR     LR, [R5, #BigDirEntries]

 [ BigDirFix
        ASSERT  BigDirEntrySize=28
        RSB     LR, LR, LR, LSL #3      ; *7
        ADD     R2, R2, LR, LSL #2      ; *7*4=28
 |
        ASSERT  BigDirEntrySize=32
        ADD     R2, R2, LR, LSL #5
 ]
        LDR     LR, [R5, #BigDirNamesSize] ; size of the heap of names

        ADD     R2, R2, LR              ; word after name heap
        ADD     R2, R2, R5

        SUB     R2, R2, R0              ; length of move

 [ DebugX
        DLINE   "Moving upper section of names"
        DREG    R0, "source="
        DREG    R1, "  dest="
        DREG    R2, "   len="
 ]

        BL      BlockMove               ; do the block move

        ADD     R7, R0, #BigDirEntrySize

        MOV     R0, R7
        MOV     R1, R6
        BL      ZeroRam                 ; zero rest of the entry

; R7 now points to start of new name heap entry

        MOV     R0, R4
        ADD     R1, R4, #BigDirEntrySize
        SUB     R2, R7, R1              ; amount to move

 [ DebugX
        DLINE   "Moving entries and lower section of names"
        DREG    R0, "source="
        DREG    R1, "  dest="
        DREG    R2, "   len="
 ]

        BL      BlockMove

; now update dir header fields
        LDR     LR, [R5, #BigDirEntries]        ; number of entries
        ADD     LR, LR, #1
        STR     LR, [R5, #BigDirEntries]        ; new number of entries

        LDR     LR, [R5, #BigDirNamesSize]      ; size of names heap
        ADD     LR, LR, R6
        STR     LR, [R5, #BigDirNamesSize]      ; new number of entries

 [ :LNOT: BigDirFix
        LDR     LR, DirE
        STR     LR, [R4, #BigDirEntryName]      ; give the entry a DirE
 ]

; finally, generate new offsets into the name heap

        ADD     R4, R4, #BigDirEntrySize

        BL      BigDirFinished                  ; (R4, R5->C)

; C=0->can use next entry
; C=1->next entry not there, so use size of heap take R6
        LDRNE   LR, [R4, #BigDirObNamePtr]
        LDREQ   LR, [R5, #BigDirNamesSize]
        SUBEQ   LR, LR, R6

        STR     LR, [R4, #BigDirObNamePtr-BigDirEntrySize]      ; copy it
;
 [ DebugX
        DREG    R8, "storing name len of:"
 ]
        STR     R8, [R4, #BigDirObNameLen-BigDirEntrySize]      ; and set the name length

; now, bump all the other name indexes up by R6

1301
        BEQ     %FT95                                           ; if Z=1 then finished
1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312

10
        LDR     LR, [R4, #BigDirObNamePtr]
        ADD     LR, LR, R6                      ; new pointer
        STR     LR, [R4, #BigDirObNamePtr]
        ADD     R4, R4, #BigDirEntrySize
        BL      BigDirFinished                  ; (R4, R5->C)
        BNE     %BT10
 [ DebugX
;       BL      DumpBigDir
 ]
1313 1314 1315
95
        RestPSR R11,,f
        Pull    "R0-R11,PC"                             ; if C=1 then finished
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336

 [ DebugX

; r5-dir start

DumpBigDir ROUT
        Push    "R5,R11,LR"                             ; save regs
        DLINE   "Directory dump:"

        LDR     R11, [R5, #BigDirSize]                  ; size of dir
10
        LDR     LR, [R5], #4                            ; get a word
        DREG    LR, " ",cc                              ; dump it
        AND     LR, R11, #4*7                           ; is it end of line
        CMPS    LR, #4*7
        BEQ     %FT01
        DLINE   " "
01
        SUBS    R11, R11, #4
        BGT     %BT10

1337
        Pull    "R5,R11,PC"
1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
 ]

; ============
; WriteBigName
; ============

; copy file name string to dir entry

; entry:
;  R1 -> name
;  R4 -> entry
;  R5 -> dir start

WriteBigName ROUT
        Push    "R0-R2,R4,LR"
 [ DebugXd
1354
        DSTRING R1, "WriteBigName : "
1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368
 ]
        LDR     R2, [R4, #BigDirObNameLen]
        ADD     R2, R2, #3
        BIC     R2, R2, #3      ; up to word boundary
        BL      GetBigDirName   ; (R4,R5->LR)
        MOV     R4, LR
10
        BL      ThisChar        ;(R1->R0,C)
        ADD     R1, R1, #1
        MOVCS   R0, #CR         ;if terminator
        STRB    R0, [R4],#1
        BCS     %FT90
        B       %BT10
90
1369
        Pull    "R0-R2,R4,PC"
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384


; ===============
; WriteBigDirName
; ===============

; copy dir name string into big dir

; entry:
; R1->name
; R5->dir

WriteBigDirName ROUT
        Push    "R0-R2,R4,R6,LR"
 [ DebugXd
1385
        DSTRING R1, "WriteBigDirName : "
1386
 ]
1387
        MOV     R6, #0
1388 1389 1390 1391 1392
        ADD     R4, R5, #BigDirHeaderSize
10
        BL      ThisChar        ;(R1->R0,C)
        ADD     R1, R1, #1
        MOVCS   R0, #CR         ;if terminator
1393
        ADDCC   R6, R6, #1
1394 1395 1396 1397
        STRB    R0, [R4],#1
        BCS     %FT90
        B       %BT10
90
1398
        STR     R6, [R5, #BigDirNameLen]
1399
        Pull    "R0-R2,R4,R6,PC"
1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415

; ================
; WriteBigDirNames
; ================

; entry: R5->start of dir
;        R6->end

WriteBigDirNames ROUT
        Push    "R11,LR"

        ADRL    R11, SBProven
        LDMIA   R11, {R11, LR}
        STR     R11, [R5, #BigDirStartName]
        STR     LR, [R6, #BigDirEndName]

1416
        Pull    "R11,PC"
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495

; =============
; TryGrowDirBuf
; =============

; entry R4 required size of dir buf

; exit

; if error, VS and R0->error

TryGrowDirBuf ROUT
        Push    "R0-R8,LR"      ; stuff
 [ DebugX
        DREG    R4,"entry TryGrowDirBuf - need: "
 ]
        ; because DA size may be rounded up to a page, we read the real size here
        MOV     R0, #2                  ; read area size
        LDR     R1, DirBufferArea       ; area addr
        BL      OnlyXOS_DynamicArea     ; do the SWI call
        BVS     %FT95

        STR     R2, DirBufferSize       ; if it's already small enough then we're OK

        LDR     R4, [SP, #4*4]          ; get back the size needed

        CMP     R4, R2                  ; do we need more space
        BLS     %FT94                   ; no

        MOV     R0, R1                  ; area number to R0
        SUB     R1, R4, R2              ; amount needed
        BL      OnlyXOS_ChangeDynamicArea
        BVS     %FT95

        ADD     R2, R2, R1              ; number of bytes added to area
        STR     R2, DirBufferSize       ; etc
94
        CLRV                            ; clear the V flag
95
        STRVS   R0, [SP]                ; if V set then store the error
 [ DebugX
        DLINE   "Exit TryGrowDirBuf"
 ]
        Pull    "R0-R8,PC"      ; other stuff

; ==========
; GrowBigDir
; ==========

; entry:

; R3  =  dir ind disc address
; R5  -> dir start
; R6  -> dir end

; dir is in DirBuffer


GrowBigDir ROUT
        Push    "R0-R11,LR"
 [ DebugX :LOR: DebugXg
        DLINE   "entering GrowBigDir"
        DREG    R3, "dir "
        DREG    R5, "at  "
 ]
; first of all, ensure have enough memory for dir of required size
        SUB     R4, R6, R5              ; current dir size
        ADD     R4, R4, #BigDirMinSize  ; add a bit to it
        BL      TryGrowDirBuf
        BVS     %FT99

; loop back to here when need to move more files
10
        LDR     R3, [SP, #3*4]
        LDR     R6, [SP, #6*4]
        LDR     R5, [SP, #5*4]
        SUB     R4, R6, R5
        ADD     R4, R4, #BigDirMinSize  ; size required
        BL      DiscAddToRec            ; get disc record
1496 1497
        LDR     R7, [LR, #DiscRecord_Log2SectorSize]   ; sector size
        LDR     LR, [LR, #DiscRecord_BigMap_ShareSize]    ; share size
1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539
        ADD     R7, R7, LR
        MOV     R11, #1
        RSB     R11, R11,R11,LSL R7
        TSTS    R4, R11
        MOV     R9, R4, LSR R7
        ADDNE   R9, R9, #1              ; sharing blocks needed for dir

 [ DebugXg
        DREG    R9, "dir needs ",cc
        DLINE   " sharing blocks"
 ]

        BL      BeforeAlterFsMap        ; (R3->R0,V)
        BVS     %FT99

        BL      CritInitReadNewFs       ; (->R10,R11)

        BL      SortDir                 ; (R3,R5->R8)

15
        LDMIA   R8!, {R4, R5}           ; get table entry
 [ DebugXg
        DREG    R5," table entry: ",cc
        DREG    R4,""
 ]
        AND     R0, R5, #&FF    ; r5 - sharing offset
        TEQS    R5, #0
        TEQEQS  R4, #0
        BEQ     %FT25           ;end of list marker found
        MOVS    R5, R5, LSR #9  ;link bits
        ADDCS   R5, R5, R3, LSR #8
        RSBCC   R5, R5, R3, LSR #8
 [ DebugXg
        DREG    R0, "File sector:",cc
        DREG    R4, ", file index:",cc
        DREG    R5, ", link bits:"
 ]

        TEQS    R4, #0          ;is it the dir itself?
        BEQ     %FT20

        TEQS    R5, R3, LSR #8  ;is it the same object as the dir
1540
        BNE     %FT25           ;note: this is a termination case due to the sorting of the dir
1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600

        CMPS    R0, #1          ;is the sharing offset 1?
        BEQ     %FT20

        CMPS    R0, R9          ;is it in the way?
        BHI     %FT20           ; no

        ; an object is in the way
 [ DebugXg
        DREG    R0,"offset in the way:"
 ]
        SUB     LR, r0, #1
        MOV     R7, LR, LSL R7          ; dummy dir size for ClaimFreeSpace
        ; find the offending dir entry

 [ BigDirFix
        ASSERT  BigDirEntrySize=28
        RSB     R4, R4, R4, LSL #3      ; *7
        MOV     R4, R4, LSL #2          ; *4*7=28
 |
        ASSERT  BigDirEntrySize=32
        MOV     R4, R4, LSL #5          ; will never be dir itself
 ]
        LDR     LR, DirBufferPtr
        LDR     LR, [LR, #BigDirNameLen]
        ADD     LR, LR, #4
        BIC     LR, LR, #3
        ADD     R4, LR, R4
        LDR     LR, DirBufferPtr
        ADD     LR, LR,#BigDirHeaderSize-BigDirEntrySize
        ADD     R4, R4, LR

  [ DebugXg
        BL      ReadIndDiscAdd          ; (R4->LR)
        DREG    LR, "Ind disc add of entry:"
  ]
        BL      ReadLen                 ; (R4->LR)
        MOV     R10, LR                 ; length to claim
        MOV     R11,#fsfile_Save        ; reason code to ClaimFreeSpace
        LDR     R5, [SP, #5*4]          ; get the dir
        ADD     R7, R7, R10             ; increase dummy length
        STR     R7, [R5, #BigDirSize]   ; fake dir size (MUST restore later - see below)
 [ DebugXg
        DREG    R7, "dummy size:"
 ]
        BL      ClaimFreeSpace          ; claim space for object
  [ DebugXg
        BVC     %FT01
        DLINE   "ClaimFreeSpace failed"
01
  ]
        LDR     R6, [SP, #6*4]          ;
        SUB     R6, R6, R5
        STR     R6, [R5, #BigDirSize]   ; restore dir's original size MUST do this
        BVS     %FT96


; loop among Fcbs until we find that matches.  if it does, then we
; then have to adjust it

1601
        BL      ReadIndDiscAdd
1602

1603 1604 1605 1606 1607 1608 1609 1610
        sbaddr  r1, FirstFcb-FcbNext
        B       %FT02
01
        LDR     r8, [r1, #FcbIndDiscAdd]
 [ DebugXg
        DREG    r8, "File in chain:"
 ]

1611
        CMP     r8, lr
1612 1613 1614 1615
        BNE     %FT02
 [ DebugXg
        DLINE   "matches file we're interested in"
 ]
1616
        BL      Flush           ;flush the file of interest
1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638
        B       %FT03
02
        LDR     r1, [r1,#FcbNext];get next FCB
        CMPS    r1, #-1
        BNE     %BT01           ;
03

        Push    "R1,R3,R4"
        BL      ReadIndDiscAdd
        MOV     R1, LR
        MOV     R3, R10
        BL      DefaultMoveData         ; move the data
        BVS     %FT96                   ; argh
        Pull    "R1,R3,R4"

        MOV     R0, R2
        BL      WriteIndDiscAdd ; update the dir
        BL      WriteFsMapThenDir       ; write the stuff out
        BVS     %FT96           ; err, this would be BAD

        ; now if we found a matching Fcb, update its ind disc address

1639 1640
        CMP     R1, #-1
        STRNE   R2, [R1, #FcbIndDiscAdd]
1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688

        BL      UnlockMap       ; unlock the map
        B       %BT10           ; and try going round the loop again

20
        B       %BT15           ; round the loop again

25      ; SortDir didn't find any objects which clash.  do the grow operation, checking
        ; it won't grow beyond MinMapObj

        BIC     R1, R3, #&ff            ; pretend to be unshared
        BL      MeasureFileAllocSize_GotMap             ; allocated size
 [ DebugXg
        DREG    R0, "space allocated to dir:"
 ]

        LDR     R5, [SP, #5*4]  ; get the dir addr again
        LDR     R7, [R5, #BigDirSize] ; size of dir at present
        ADD     R7, R7, #BigDirMinSize
        CMPS    R7, R0
        BLS     %FT58

        ; here we don't have any shared objects getting in the way, but we
        ; don't have enough space allocated (how convenient).

        ; we call ClaimFreeSpace with RandomAccessExtend reason code to
        ; get things sorted out.  but we cheat.  because, y see, we don't
        ; want to have to get the parent dir in just yet, with all that
        ; copying around of data, so I'm gonna build a dummy dir entry
        ; on the stack.  cunning, eh no?

        ; we also then return most of the space anyway, cos RandomAccessExtend
        ; has a tendency to allocate far too much space

        Push    "R3,R4,R6,R7"

        SUB     SP, SP, #BigDirEntrySize        ; space for an entry
        MOV     R4, SP
        MOV     R6, R3                  ; keep addy around
        BL      ToParent                ; get parent addy
        BIC     R6, R6, #DiscBits       ; knock off DiscBits
        BIC     R6, R6, #&ff            ; and pretend unshared
        STR     R6, [R4, #BigDirIndDiscAdd]
        SUB     LR, R7, #BigDirMinSize  ; current size
        STR     LR, [R4, #BigDirLen]

        ; only need IndDiscAdd and Len to be valid in the dummy entry.

1689
 [ {FALSE}
1690 1691
        ADD     R7, R7, #262144         ; 64K allocation?
        MOV     R10, R7
1692 1693 1694 1695 1696 1697 1698 1699
 |
        MOV     R10, R7                 ; size wanted
 ]
        MOV     R0, LR                  ; old extent
        MOV     R11, #RandomAccessExtend
        BL      ClaimFreeSpace          ; (R0,R3,R4,R5,R10,R11->R0,R2,R10,V)
        BVS     %FT55

1700
        MOV     R0, R10
1701 1702 1703

        Push    "R0,R2,R4,R5,R8,R10"

1704
        MOV     R0, R7
1705

1706
        BL      CritInitReadNewFs       ; (->R10, R11)