• Ben Avison's avatar
    Commit of kernel as featured in release 5.00. · 9664c93b
    Ben Avison authored
    Detail:
      Lots of changes since last version, at least the following:
      * Updated OS timestamp, removed alpha status
      * Negative INKEY OS version changed to &AA
      * GraphicsV is now alocated vector number &2A
      * ROM moved up to &FC000000
      * Max application slot increased to 512 Mbytes (for now)
      * Max size of RMA increased to 256 Mbytes
      * RMA is now first-created dynamic area (so it gets lowest address after
        top of application slot)
      * OS_Memory 10 reimplemeted
      * New OS_ReadSysInfo 6 values 18-22 added
      * OS_ReadSysInfo 8 gains flag bit to indicate soft power-off
      * Misc internal top-bit-set-address fixes
      * *ChangeDynamicArea can take sizes in megabytes or gigabytes
      * Magic word "&off" in R0 passed to OS_Reset powers down if possible
      * Added acceleration: block copy; CLS; text window scroll up; rectangle
        fill
      * Disabled LED flashing in page mode (liable to crash)
      * Masked sprite plot and VDU 5 text avoids reading the screen if possible
      * Framestore made USR mode accessible
      * Fix for VDU 5,127 bug - now relies on font definitions being in extreme
        quarters of memory, rather than bottom half
      * Allocated 64-bit OS_Convert... SWIs
      * IIC errors use allocated error numbers
      * Looks for Dallas RTC before Philips RTC because we're using a Philips
        NVRAM device with the same ID
      * Fix to bug that meant the oscillator in the Dallas RTC wasn't enabled
      * Default mouse type (USB) changed to allocated number
      * Ram disc max size increased to 128 Mbytes (Ursula merge) and made
        cacheable for StrongARMs (not XScale)
      * Branch through zero handler now works in USR mode, by use of a
        trampoline in the system stack to allow PC-relative register storage
      * Address exception handler changed to not use 0 as workspace
      * OS_Memory 13 extended to allow specification of cacheability and access
        privileges
      * Added OS_Memory 16 to return important memory addresses
      * RISCOS_MapInIO() takes cacheable flag in bit 3, access permissions in
        bits 10 and 11, doubly-mapped flag in bit 20, and access permissions
        specified flag in bit 21
      * Bug fix in last version for application abort handlers didn't quite
        work; register shuffle required
      * "Module is not 32-bit compatible" error now reports the module name
      * Default configured language changed from 10 to 11 (now Desktop again)
    
    Version 5.35, 4.79.2.51. Tagged as 'Kernel-5_35-4_79_2_51'
    9664c93b
vdu5 20.9 KB
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 33 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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 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 243 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 582 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 644 645 646 647 648 649 650 651 652 653 654 655 656
; Copyright 1996 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.
;
; > $.Source.Vdu5

; *****************************************************************************
;
;       Print a character in VDU 5 mode
;

; *****This file has been extensively modified by DJS

; Alter these at your peril !

cxl     RN      0
scr     RN      0

ecfptr  RN      1
cword0  RN      1

cyb     RN      2
cyt2    RN      2
scrend  RN      2
cword1  RN      2

cxr     RN      3
cyb2    RN      3
ormask  RN      3

cxl2    RN      4
eormask RN      4

cyb3    RN      5
charmsk RN      5
cword2  RN      5

cyt     RN      6
llength RN      6
chartmp RN      6

sizex   RN      7
charptr RN      7

sizey   RN      8
invcharshf RN   8

charbyte RN     9

cxr2    RN      10
charshf RN      10

lgBPC   RN      11

Vdu5Wrch
        Push    R14
        BL      Vdu5DoChar
        Pull    R14
        B       PostCharMove

; Vdu23_18
;        LDR     R0, [WsPtr, #QQ+1]
Vdu5DoChar
        ADD     ecfptr, WsPtr, #FgEcfOraEor  ;Base address of OR/EOR pairs
Vdu5DoChar10
        Push    "R14"
        MOV     charbyte, R0                    ;Put character out of harm's
                                                ;  way
        ASSERT  cxl < cyt
        ASSERT  GCsIY = GCsIX +4
        ADD     cxl, WsPtr, #GCsIX
        LDMIA   cxl, {cxl, cyt}                 ; cxl=where left pixel would be
                                                ; cyt=where top pixel would be

        ASSERT  sizex < sizey
        ADD     sizex, WsPtr, #GCharSizes
        LDMIA   sizex, {sizex, sizey}
        CMP     sizey, #16                      ; if SizeY=8 or SizeY=16
        TEQNE   sizey, #8                       ;   (leaving CS <=> SizeY=16)
        TEQEQ   sizex, #8                       ; and SizeX=8, then do it fast
        BNE     SlowVdu5                        ; else do by scaled char

        TEQ     charbyte, #127                  ; Which font do we use?
        ADDNE   charptr, WsPtr, #(Font-32*8)    ; Soft if character not DELETE
        ADREQL  charptr, HardFont-32*8          ; Hard if character is DELETE
        ADD     charptr, charptr, charbyte, LSL #3      ;Point at char def

        MOVCS   charptr, charptr, ASL #1        ; Double address if SizeY = 16
        SUBCS   charptr, charptr, #1            ;   (tricky code, originally
                                                ;   designed by TMD)

        SUB     cyb, cyt, sizey
        ADD     cyb, cyb, #1                    ; where bottom pixel would be
        ADD     cxr, cxl, #7                    ; where right pixel would be

        ASSERT  GWBRow = GWLCol+4
        ASSERT  GWRCol = GWLCol+8
        ASSERT  GWTRow = GWLCol+12
        ASSERT  cyb3 > cxl2
        ASSERT  cxr2 > cyb3
        ASSERT  R14 > cxr2
        ADD     cxl2, WsPtr, #GWLCol
        LDMIA   cxl2, {cxl2, cyb3, cxr2, R14}

        Greatest cxl2, cxl2, cxl                ; cxl2 := windowed left
                                                ;   (2 instructions)
        Least   cxr2, cxr2, cxr                 ; cxr2 := windowed right
                                                ;   (2 instructions)
        Greatest cyb2, cyb3, cyb                ; cyb2 := windowed bottom
                                                ;   (3 instructions)
        Least   cyt2, R14, cyt                  ; cyt2 := windowed top
                                                ;   (3 instructions)

        SUBS    cyb2, cyt2, cyb2                ; top >= bottom ?
        CMPGE   cxr2, cxl2                      ; and right >= left ?
        Pull    "PC", LT                        ; Exit if not. Otherwise cyb2
                                                ;   has become clipped height

        LDR     R14, [WsPtr, #CursorFlags]      ; update changed box, if wanted
        TST     R14, #ClipBoxEnableBit
        BLNE    ClipVdu5

        ADD     charptr, charptr, cyt           ; adjust charptr to point at
        SUB     charptr, charptr, cyt2          ;   first used row of character

        MOV     charmsk, #&FF                   ; Produce mask to do left/right
        SUB     R14, cxl2, cxl                  ;   clipping
        MOV     charmsk, charmsk, LSR R14
        SUB     R14, cxr2, cxl2
        ADD     R14, R14, #1
        BIC     charmsk, charmsk, charmsk, LSR R14

        TEQ     sizey, #16                      ; If double height, signal this
        ORREQ   charmsk, charmsk, #1:SHL:31     ;   by making charmsk negative

        ASSERT  llength > scr
        ASSERT  LineLength = YWindLimit+4
        LDR     lgBPC, [WsPtr, #Log2BPC]        ; Address point at (cxl, cyt2),
        MOV     charshf, cxl, LSL lgBPC         ;   putting address in scr, bit
        ADD     scr, WsPtr, #YWindLimit         ;   offset in charshf and
        LDMIA   scr, {scr, llength}             ;   adjusting ecfptr
        SUB     scr, scr, cyt2
        AND     R14, scr, #7
        ADD     ecfptr, ecfptr, R14, LSL #3
        LDR     R14, [WsPtr, #ScreenStart]
        MLA     scr, llength, scr, R14
        MOV     R14, charshf, ASR #5
        ADD     scr, scr, R14, LSL #2
        AND     charshf, charshf, #31

        MLA     scrend, llength, cyb2, scr      ;Calculate terminating address

        RSB     invcharshf, charshf, #32        ;And inverse shift

Vdu5NextLine
        ASSERT  eormask > ormask
        LDMIA   ecfptr!, {ormask, eormask}      ;Pick up ecf info and advance
        TST     ecfptr, #63                     ;  ecf pointer, wrapping if
        SUBEQ   ecfptr, ecfptr, #64             ;  necessary

        ASSERT  HardFont < &40000000 :LOR: HardFont >= &C0000000
        ASSERT  WsPtr < &40000000 :LOR: WsPtr >= &C0000000
        TEQ     charmsk, #0                     ; Double height? (MI=yes)
        LDRMIB  charbyte, [charptr, -charptr, ASR #1] ; Use ASR, as font will be at
        LDRPLB  charbyte, [charptr]             ; top or bottom of memory (zero page,
        ADD     charptr, charptr, #1            ; system heap or ROM)

        ANDS    charbyte, charbyte, charmsk     ;Clip left & right; skip loop
        BEQ     Vdu5TryNextLine                 ;  body if nothing to plot

        Push    "ecfptr,scrend,charmsk,llength,charptr"

        LDR     R14, [WsPtr, #TextExpandArea]   ;Address correct expansion

        ADD     charptr, charbyte, #&100        ;  table entry, assuming that
        ADD     charptr, R14, charptr, LSL lgBPC        ;  this is not mode 10 or greater

        CMP     lgBPC, #1                       ;Pick up this entry:
        LDRLSB  cword0, [charptr, #0]           ;  1 byte if lgBPC = 0
        LDREQB  R14, [charptr, #1]              ;  2 bytes if lgBPC = 1
        ORREQ   cword0, cword0, R14, LSL #8
        MOV     cword1, #0
        BLS     Vdu5DoOneWord
        CMP     lgBPC, #3
        LDRLO   cword0, [charptr, #0]           ;  1 word if lgBPC = 2
        BLO     Vdu5DoOneWord
        BHI     Vdu5Mode10                      ;  4 words if lgBPC = 4
        LDMIA   charptr, {cword0, cword1}       ;  2 words if lgBPC = 3
        MOVS    cword2, cword1, LSR invcharshf

        MACRO
$l      DoVdu5Word $c, $reg, $off
$l
        LDR$c   chartmp, [scr, #$off]
        AND$c   R14, ormask, $reg
        ORR$c   chartmp, chartmp, R14
        AND$c   R14, eormask, $reg
        EOR$c   chartmp, chartmp, R14
        STR$c   chartmp, [scr, #$off]
        MEND

Vdu5DoTwoWords
        DoVdu5Word NE, cword2, 8
        MOV     cword1, cword1, LSL charshf
Vdu5DoOneWord
        ORRS    cword1, cword1, cword0, LSR invcharshf
        DoVdu5Word NE, cword1, 4
        MOVS    cword0, cword0, LSL charshf
        DoVdu5Word NE, cword0, 0

Vdu5LinePainted
        Pull    "ecfptr,scrend,charmsk,llength,charptr"

Vdu5TryNextLine
        TEQ     scr, scrend
        ADDNE   scr, scr, llength
        BNE     Vdu5NextLine

        Pull    "PC"

; This is mode 10 (or similar) - we must do bit expansion on the fly

Vdu5Mode10
        CMP     lgBPC, #5                       ; is this a 32 bit per pixel mode, if so then ignore the
        BEQ     Vdu5Mode32                      ; existing code and use a newer function

        ADRL    charptr, C16BTab
        AND     R14, charbyte, #&0F
        ADD     R14, charptr, R14, LSL #3
        LDMIA   R14, {cword0, cword1}

        MOVS    cword2, cword1, LSR invcharshf
        DoVdu5Word NE, cword2, 16
        MOV     cword1, cword1, LSL charshf
        ORRS    cword1, cword1, cword0, LSR invcharshf
        DoVdu5Word NE, cword1, 12
        MOVS    cword2, cword0, LSL charshf

        AND     R14, charbyte, #&F0
        ADD     R14, charptr, R14, LSR #1
        LDMIA   R14, {cword0, cword1}
        ORRS    cword2, cword2, cword1, LSR invcharshf
        B       Vdu5DoTwoWords

; Expand the character data out to 32 bit per pixel (mode 48 or similar)

        MACRO
$l      PixMunge32 $reg, $mask, $offset
$l
        TST     $reg, #$mask
        LDRNE   chartmp, [scr, #$offset]
        ORRNE   chartmp, chartmp, ormask
        EORNE   chartmp, chartmp, eormask
        STRNE   chartmp, [scr, #$offset]
        MEND

        MACRO
$l      PixSolid32 $reg, $mask, $offset
$l
        TST     $reg, #$mask
        STRNE   chartmp, [scr, #$offset]
        MEND

; Perform bit expansion on the fly, this is a word based operation, no need to
; extract sub-pixels from the ORR / EOR masks, simply perform the bit test and
; then write the character data to the screen!

Vdu5Mode32

 [ AvoidScreenReads
        CMP     ormask, #&FFFFFFFF
        BNE     Vdu5Mode32_NotSolid

        MVN     chartmp, eormask
        PixSolid32 charbyte, 1<<7, 0
        PixSolid32 charbyte, 1<<6, 4
        PixSolid32 charbyte, 1<<5, 8
        PixSolid32 charbyte, 1<<4, 12
        PixSolid32 charbyte, 1<<3, 16
        PixSolid32 charbyte, 1<<2, 20
        PixSolid32 charbyte, 1<<1, 24
        PixSolid32 charbyte, 1<<0, 28

        B       Vdu5LinePainted

Vdu5Mode32_NotSolid
 ]
        PixMunge32 charbyte, 1<<7, 0
        PixMunge32 charbyte, 1<<6, 4
        PixMunge32 charbyte, 1<<5, 8
        PixMunge32 charbyte, 1<<4, 12
        PixMunge32 charbyte, 1<<3, 16
        PixMunge32 charbyte, 1<<2, 20
        PixMunge32 charbyte, 1<<1, 24
        PixMunge32 charbyte, 1<<0, 28

        B       Vdu5LinePainted                 ; flow down and try the next line


; *****************************************************************************
;
;       Slow VDU 5 - Print char by scaled method (in SprExtend)
;
; in:   R1 (ecfptr)   = pointer to ecf pattern
;       R7 (sizex)    = SizeX
;       R8 (sizey)    = SizeY
;       R9 (charbyte) = character to plot
;
;       Stack:  Return address
;

        ASSERT  ecfptr   = R1
        ASSERT  sizex    = R7
        ASSERT  sizey    = R8
        ASSERT  charbyte = R9

SlowVdu5 ROUT

        MOV     R10, R1                         ; R10 := ecfptr

; now save current GCOL on stack if necessary

        ADD     R11, WsPtr, #FgEcfOraEor
        TEQ     R10, R11                        ; if going to use this one
        BEQ     %FT20                           ; then skip

        MOV     R0, #64                         ; 64 bytes
10
        LDMIA   R11, {R3-R6}                    ; copy old GCOL into stack
        Push    "R3-R6"                         ;   frame, reversing order of
                                                ;   16 byte chunks
        LDMIA   R10!, {R3-R6}                   ; copy new colour
        STMIA   R11!, {R3-R6}                   ; into GCOL
        SUBS    R0, R0, #16
        BNE     %BT10

20
        MOV     R4, #8
        MOV     R5, #8
        Push    "R4,R5"
        Push    "R7,R8"
        MOV     R6, R13                         ; R6 -> scaling block

        SUB     R1, R8, #1                      ; SizeY-1
        LDR     R5, [WsPtr, #YEigFactor]
        ADD     R3, WsPtr, #GCsX
        LDMIA   R3, {R3, R4}                    ; R3 = ext X; R4 = ext Y (top)
        SUB     R4, R4, R1, LSL R5              ; R4 = ext Y (bottom)
        MOV     R1, R9                          ; R1 = char
        MOV     R0, #SpriteReason_PaintCharScaled
        SWI     XOS_SpriteOp

        ADD     R13, R13, #4*4                  ; junk scaling block

        TEQ     R10, R11                        ; if we didn't copy GCOLs
        Pull    "PC", EQ                        ; then return, else copy back

        MOV     R0, #64
30
        Pull    "R3-R6"                         ; Reverse order of 16 byte
        STMDB   R11!, {R3-R6}                   ; chunks during copy again
        SUBS    R0, R0, #16
        BNE     %BT30
        Pull    PC


; *****************************************************************************
;
;       VDU 5 - Start printing text at graphics cursor

ENQ
        GraphicsMode R0
        MOVNE   PC, R14

        MOV     R1, #0
        BSR     CursorOnOff                     ; turn cursor off without
                                                ; saving to copy

        LDR     R6, [WsPtr, #CursorFlags]
        ORR     R6, R6, #Vdu5Bit
        B       R6toCursorFlags

; *****************************************************************************
;
;       VDU 4 - Return to printing text at text cursor

EOT
        GraphicsMode R0
        MOVNE   PC,LR

        MOV     R1, #1
        BSR     CursorOnOff                     ; restore cursor from copy

        LDR     R6, [WsPtr, #CursorFlags]
        BIC     R6, R6, #Vdu5Bit
        B       R6toCursorFlags

; *****************************************************************************
;
;       Vdu5HT - Move cursor "right" when in VDU 5 mode
;
; in:   R6 = CursorFlags

Vdu5HT
        Push    R14
        BL      GCursorMove             ; try to move in +ve X direction
        BCC     EndVdu5HT               ; if successful, finish
        BL      GCursorB0               ; else move cursor to -ve X boundary
Vdu5HT10
        EOR     R6, R6, #8              ; change to +ve Y direction
        BL      GCursorMove             ; try to move in that direction
        BLCS    GCursorB0               ; if unsuccessful, move to -ve Y bdy
EndVdu5HT
        Pull    R14
        B       IEG

; *****************************************************************************
;
;       Vdu5BS - Move cursor "left" when in VDU 5 mode
;
; in:   R6 = CursorFlags

Vdu5BS
        EOR     R6, R6, #6              ; go to -ve X direction
        B       Vdu5HT                  ; dead easy, huh ?

; *****************************************************************************
;
;       Vdu5LF - Move cursor "down" when in VDU 5 mode
;
; in:   R6 = CursorFlags

Vdu5LF
        Push    R14
        B       Vdu5HT10

; *****************************************************************************
;
;       Vdu5VT - Move cursor "up" when in VDU 5 mode
;
; in:   R6 = CursorFlags

Vdu5VT
        EOR     R6, R6, #6              ; go to -ve Y direction (eventually)
        B       Vdu5LF

; *****************************************************************************
;
;       Vdu5CR - Carriage return in VDU 5 mode
;
; in:   R6 = CursorFlags

Vdu5CR
        BSR     GCursorB0
        B       IEG

; *****************************************************************************
;
;       Vdu5FF - Clear screen in VDU 5 mode
;
; in:   R6 = CursorFlags

Vdu5FF
        BSR     Home
        B       CLG

; *****************************************************************************
;
;       Vdu5TAB - TAB(X,Y) in VDU 5 mode
;
; in:   R0 = X, R1 = Y, R6 = CursorFlags

Vdu5TAB
        BSR     GCursorBdy
        EOR     R6, R6, #8
        MOV     R0, R1
        BSR     GCursorBdy
        B       IEG

; *****************************************************************************
;
;       Vdu5Delete - Delete in VDU 5 mode (already done backspace)
;
; in:   R6 = CursorFlags

Vdu5Delete
        ADD     ecfptr, WsPtr, #BgEcfStore ; STORE background colour/ecf
        MOV     R0, #127                   ; uses hard font for this char
        B       Vdu5DoChar10

; *****************************************************************************
;
;       GCursorMove - Move graphics cursor in direction specified by R6
;       (0,4 = right; 2,6 = left; 8,10 = down; 12,14 = up)
;       R6 is preserved

GCursorMove
        ADD     R0, WsPtr, #GCsIX
        LDMIA   R0, {R0, R1}                    ; R0 = GCsIX; R1 = GCsIY
        ADD     R2, WsPtr, #GCharSpacing+8      ; +8 needed to address it
        LDMDB   R2, {R2, R3}                    ; R2=GCharSpaceX;R3=GCharSpaceY
        WINDow  R0, R1, R8,R9,R10,R11           ; return LT if outside window
        ADR     R7, GCMVTab
        B       DoJumpTable

GCMVTab
        &       GMoveRight-GCMVTab
        &       GMoveLeft-GCMVTab
        &       GMoveRight-GCMVTab
        &       GMoveLeft-GCMVTab
        &       GMoveDown-GCMVTab
        &       GMoveDown-GCMVTab
        &       GMoveUp-GCMVTab
        &       GMoveUp-GCMVTab

; Move graphics cursor right if possible - on exit C=0 iff OK to move

GMoveRight
        ADD     R0, R0, R2              ; add on GCharSpaceX
GMove10
        STR     R0, [WsPtr, #GCsIX]
GMove15
        BLT     GMoveOK                 ; if we were outside already
        TST     R6, #&40                ; or we are in nowrap mode
        BNE     GMoveOK                 ; then we were OK to move
        WINDow  R0, R1, R8,R9,R10,R11
        BGE     GMoveOK                 ; if inside now, then OK
        SEC
        MOV     PC, R14

GMoveOK
        CLC
        MOV     PC, R14

; Move graphics cursor left if possible - on exit C=0 iff OK to move

GMoveLeft
        SUB     R0, R0, R2              ; subtract off GCharSpaceX
        B       GMove10

; Move graphics cursor down if possible - on exit C=0 iff OK to move

GMoveDown
        SUB     R1, R1, R3              ; subtract off GCharSpaceY
GMove20
        STR     R1, [WsPtr, #GCsIY]
        B       GMove15

; Move graphics cursor up if possible - on exit C=0 iff OK to move

GMoveUp
        ADD     R1, R1, R3              ; add on GCharSpaceY
        B       GMove20

; *****************************************************************************
;
;       Move graphics cursor to boundary indicated by value of R6 in bits 1-3
;       (0 or 4 = left, 2 or 6 = right, 8 or 10 = up, 12 or 14 = down)
;       + R0 character positions in
;

GCursorB0
        MOV     R0, #0
GCursorBdy
        ADR     R7, GCBDYTab
        B       DoJumpTable

GCBDYTab
        &       GCursorLBdy-GCBDYTab
        &       GCursorRBdy-GCBDYTab
        &       GCursorLBdy-GCBDYTab
        &       GCursorRBdy-GCBDYTab
        &       GCursorUBdy-GCBDYTab
        &       GCursorUBdy-GCBDYTab
        &       GCursorDBdy-GCBDYTab
        &       GCursorDBdy-GCBDYTab

; Move graphics cursor to left boundary + R0 characters in

GCursorLBdy
        LDR     R7, [WsPtr, #GWLCol]
        LDR     R2, [WsPtr, #GCharSpaceX]
        MLA     R0, R2, R0, R7                  ; GCsIX := GWLCol + (X*SpaceX)
        STR     R0, [WsPtr, #GCsIX]
        MOV     PC, R14

; Move graphics cursor to right boundary + R0 characters in
; (adjust for character size)

GCursorRBdy
        LDR     R7, [WsPtr, #GWRCol]
        LDR     R2, [WsPtr, #GCharSizeX]
        SUB     R7, R2, R7                      ; R7 = SizeX-GWRCol
        LDR     R2, [WsPtr, #GCharSpaceX]
        MLA     R0, R2, R0, R7                  ; R0 = SizeX-GWRCol+X*SpaceX
        RSB     R0, R0, #1                      ; GWRCol-X*SpaceX-(SizeX-1)
        STR     R0, [WsPtr, #GCsIX]
        MOV     PC, R14

; Move graphics cursor to up boundary + R0 characters in

GCursorUBdy
        LDR     R7, [WsPtr, #GWTRow]
        LDR     R2, [WsPtr, #GCharSpaceY]
        RSB     R2, R2, #0                      ; -SizeY
        MLA     R0, R2, R0, R7                  ; GWTRow-Y*SizeY
        STR     R0, [WsPtr, #GCsIY]
        MOV     PC, R14

; Move graphics cursor to down boundary + R0 characters in
; (adjust for character size)

GCursorDBdy
        LDR     R7, [WsPtr, #GWBRow]
        LDR     R2, [WsPtr, #GCharSpaceY]
        MLA     R0, R2, R0, R7                  ; GWBRow+Y*SpaceY
        LDR     R2, [WsPtr, #GCharSizeY]
        ADD     R0, R0, R2
        SUB     R0, R0, #1                      ; GWBRow+Y*SpaceY+(SizeY-1)
        STR     R0, [WsPtr, #GCsIY]
        MOV     PC, R14

; *****************************************************************************
;
;       ClipVdu5 - Add a VDU 5 char to clip box
;
; in:   cxl2 = left
;       cyb2 = top-bottom
;       cxr2 = right
;       cyt2 = top
;
; out:  All registers preserved
;

        ASSERT  (cxl2=R4) :LAND: (cyb2=R3) :LAND: (cxr2=R10) :LAND: (cyt2=R2)

ClipVdu5 ROUT
        Push    "R0-R3, R4, R10, R14"
        MOV     R0, cxl2
        SUB     R1, cyt2, cyb2       ; top-(top-bottom) = bottom
        MOV     R3, cyt2
        MOV     R2, cxr2
        BL      MergeClipBox
        Pull    "R0-R3, R4, R10, PC"

        END