vdugrafg 87.9 KB
Newer Older
Neil Turton's avatar
Neil Turton committed
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
; 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.VduGrafG
;
; ARTHUR OPERATING SYSTEM - Vdu Drivers
; =======================
;
; Vdu driver code - Sprite stuff
;
; Author R C Manby
; Date   10.11.86
;

RangeB * 256
RangeC * 512

; Macros for various sprite operations

        MACRO
        KillSpChoosePtr
        MOV     R0, #0
        STR     R0, [WsPtr, #SpChoosePtr]
        MEND

        MACRO
        CopyDown $to,$from,$bytes, $tmp, $tmp2
        LDR     $tmp2, [WsPtr, #VduSprite]      ; sprite being output to by Vdu
        ADD     $tmp, $from, $bytes
        SUB     $tmp, $tmp, #1                  ; from + bytes -1
        CMP     $tmp2, $to                      ; if VOTS >= to
        CMPCS   $tmp, $tmp2                     ; and from+bytes-1 >= VOTS
        BCC     %FT00
        Push    "R0, R14"
        SUB     R0, $to, $from                  ; then adjust address vars
        BL      AdjustSpriteAddress             ; by offset = to-from
        Pull    "R0, R14"
00
        CMP     $bytes, #0                      ; bytes must be a multiple of 4
01
        LDRNE   $tmp, [$from], #4
        STRNE   $tmp, [$to], #4
        SUBNES  $bytes, $bytes, #4
        BNE     %BT01
        MEND

        MACRO
        CopyUp $to,$from,$bytes, $tmp, $tmp2
        LDR     $tmp2, [WsPtr, #VduSprite]      ; sprite being output to by Vdu
        ADD     $tmp, $to, $bytes
        SUB     $tmp, $tmp, #1                  ; to + bytes -1
        CMP     $tmp2, $from                    ; if VOTS >= from
        CMPCS   $tmp, $tmp2                     ; and to+bytes-1 >= VOTS
        BCC     %FT00
        Push    "R0, R14"
        SUB     R0, $to, $from                  ; then adjust address vars
        BL      AdjustSpriteAddress             ; by offset = to-from
        Pull    "R0, R14"
00
01
        SUBS    $bytes, $bytes, #4
        LDRCS   $tmp, [$from, $bytes]
        STRCS   $tmp, [$to, $bytes]
        BHI     %BT01
        MEND

; copy R0 bytes from R3 to R2 (R2+:=R0; R3+:=R0)
; corrupts R0, R4-R11, R14
; NB not used at present

        MACRO
        CopyDownFast
        SUBS    R0, R0, #9*4
10
        LDMCSIA R3!, {R4-R11,R14}
        STMCSIA R2!, {R4-R11,R14}
        SUBCSS  R0, R0, #9*4
        BCS     %BT10
        ADDS    R0, R0, #9*4
20
        LDRNE   R4, [R3], #4
        STRNE   R4, [R2], #4
        SUBNES  R0, R0, #4
        BNE     %BT20
        MEND

        MACRO
        ClearWords $from,$words, $tmp
        MOV     $tmp,#0
01
        SUBS    $words, $words, #1
        STRCS   $tmp, [$from], #4
        BHI     %BT01
        MEND

; *****************************************************************************
;
;       AdjustSpriteAddress - Move VduSprite, ScreenStart, CursorAddr and
;        InputCursorAddr by R0
;
;       Internal routine, called by routines that use macros
;        CopyDown, CopyUp
;
; in:   R0 = no. of bytes to add on (can be -ve)
;

AdjustSpriteAddress ROUT
        Push    R14
        LDR     R14, [WsPtr, #VduSprite]
        ADD     R14, R14, R0
        STR     R14, [WsPtr, #VduSprite]
        LDR     R14, [WsPtr, #ScreenStart]
        ADD     R14, R14, R0
        STR     R14, [WsPtr, #ScreenStart]
        B       AdjustCursorVars        ; update CursorAddr, InputCursorAddr

; *****************************************************************************
;
;       SpriteInit - Setup sprite workspace on reset (called whenever break
;                    is pressed)
;

SpriteInit ROUT
        Push    R14

        BL      ClearSpritePtrName      ; clear SpChoosePtr,SpChooseName

        Pull    PC

        LTORG

; *****************************************************************************
;
;       Vdu23_27 - SCHOOSE/SGET a numbered sprite
;
; in:   QQ?0 = 0 => Select sprite STR$(QQ?1) for plotting
;       QQ?0 = 1 => Sget an area of screen and put it in sprite STR$(QQ?1)
;

Vdu23_27 ROUT
        LDRB    R0, [WsPtr, #QQ+1]
        CMP     R0, #1
        MOVCC   R3, #SpriteReason_SelectSprite          ; 0-Select sprite
        MOVEQ   R3, #SpriteReason_GetSprite             ; 1-Pickup sprite
        MOVHI   PC, R14

        Push    R14

        LDRB    R0, [WsPtr, #QQ+2]      ; sprite number
        ADD     R1, WsPtr, #NameBuf
        MOV     R2, #4
        SWI     XOS_BinaryToDecimal
        MOV     R0, #13
        STRB    R0, [R1, R2]            ; $NameBuf := STR$(n)

        MOV     R0, R3                  ; R0 = sprite-op reason code
        MOV     R2, R1                  ; R2 -> sprite name
        MOV     R3, #0                  ; extension gap size
        SWI     XOS_SpriteOp            ; perform operation, ignore errors

        Pull    PC

; *****************************************************************************
;
;       SpritePlot - PLOT &E8-&EF,X,Y
;
; in:   R2 = plot code
;
; The 2 LSBits of the plot code specify fg/bg colour and action as :-
;  0 => No effect eqv. of Gcol(5,c)
;  1 => Plot sprite using foreground Gcol action
;  2 => Invert eqv. of Gcol(4,c)
;  3 => Plot mask in background colour and Gcol action
;

SpritePlot ROUT
        Push    R14

        AND     R3, R2, #3              ; 2 LSBits of plot code
        CMP     R3, #1
        MOVCC   R5, #5                  ; gcol action - no effect
        LDREQ   R5, [WsPtr, #GPLFMD]    ;              foreground
        MOVHI   R5, #4                  ;              invert or background

        AND     R5, R5, #&0F            ; knock out any ecf bits

        LDR     R2, [WsPtr, #SpChoosePtr]      ; If ChoosePtr <> 0
        CMP     R2, #0
        BNE     %FT10                   ; then use as pointer to sprite

        MOV     R0, #SpriteReason_SelectSprite ; else select it first
        LDR     R2, =SpChooseName
        ADD     R2, R2, WsPtr           ; sprite name ptr
        SWI     XOS_SpriteOp
        LDR     R2, [WsPtr, #SpChoosePtr]

10                                      ; R2 points to the sprite
        CMP     R3, #3
        MOVNE   R0, #RangeC+SpriteReason_PutSprite
        LDREQ   R0, =RangeC+SpriteReason_PlotMask
        LDR     R1, [WsPtr, #SpAreaStart]
        SWI     XOS_SpriteOp            ; perform operation, ignoring errors

        Pull    PC

; *****************************************************************************
;
;       SwiSpriteOp - Entry point for SWI OS_SpriteOp
;
; in:   R0 = sprite op reason code
;       R1 -> sprite area (usually)
;       R2 -> sprite (usually)
;       R3..? parameters
;

SwiSpriteOp ROUT
        Push    R14
        BranchNotJustUs %F10, SpriteV, R11, R14

; we are sole owners of SpriteV, so call our internal routine

        Push    PC                      ; push address of SwiSpriteReturn
        B       SpriteVecHandler
        &       0

SwiSpriteReturn
        Pull    R14
        ORRVS   R14, R14, #V_bit        ; if error, set V_bit in link
        ExitSWIHandler

; we are not the sole owners of SpriteV, so call the vector

10
        MOV     R10, #SpriteV
        BL      %FT20
        Pull    R14
        ORRVS   R14, R14, #V_bit        ; if error, set V_bit in link
        ExitSWIHandler

20
        CallAVector

; *****************************************************************************
;
;       SpriteVecHandler - Default owner of SpriteV
;
; in:   R0-R7 contain our entry parameters
;
; out:  R0-R7 contain exit parameters
;       R8-R12 are preserved
;

        MACRO
        SpriteOpDispatch $cond
        ADD$cond PC, R10, R11, ASR #8
        MEND

        MACRO
        SpriteOpEntry   $addr, $flags
        &       (($addr - SwiSpriteOpCallTb) :SHL: 8) + $flags
        MEND

; The end of this code is put before the beginning, so that
; SpriteDispatchReturn + SVC_mode is within ADR reach of the dispatcher

BadReasonCode ROUT
        ADRL    R0, SpriteErr_BadReasonCode
      [ International
        BL      TranslateError
      ]
        B       %FT20
SpriteIsCurrentDest
        ADRL    R0, SpriteErr_SpriteIsCurrentDest
      [ International
        BL      TranslateError
      ]
        B       %FT20

15
        ADRL    R0, SpriteErr_DoesntExist
      [ International
        BL      TranslateError
      ]

20                                      ; Exit SWI with error, error code in R0
        STR     R0, [WsPtr, #RetnReg0]
30
        SETV                            ; indicate an error

; and drop thru to...

SpriteDispatchReturn
        ADD     R11, WsPtr, #RetnReg0
        LDMIA   R11, {R0-R9}            ; Restore R0-R9
        MOV     R10, R13                ; Point at old returned registers
        Push    "R0-R9"                 ; Save new returned registers on stack
        LDMIA   R10, {R0-R9}            ; Load old returned registers
        STMIA   R11, {R0-R9}            ; and put them in the dump area
        Pull    "R0-R9"                 ; restore new returned registers
        ADD     R13, R13, #10*4         ; remove stack frame
        Pull    "R10-R12,PC"

SpriteVecHandler
        Push    "R10-R12"
Kevin Bracey's avatar
Kevin Bracey committed
316
        WritePSRc SVC_mode, WsPtr       ; Re-enable interupts
Neil Turton's avatar
Neil Turton committed
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335

        VDWS    WsPtr                   ; Point R12 at Vdu driver workspace
        ADD     R11, WsPtr, #RetnReg0

        SUB     R13, R13, #10*4         ; Create stack frame for old RetnRegs
        MOV     R10, R13                ; Keep pointer to this frame
        Push    "R0-R9"                 ; Save new regs while we copy old ones
        LDMIA   R11, {R0-R9}            ; Load old regs
        STMIA   R10, {R0-R9}            ; and push them onto stack
        Pull    "R0-R9"                 ; Restore new regs
        STMIA   R11, {R0-R9}            ; Dump R0-R9

        CMP     R0, #RangeC + &100      ; if top bits out of range
        BCS     BadReasonCode           ; then error

        CMP     R0, #RangeB             ; if Range A type
        LDRCC   R1, [WsPtr, #SpAreaStart] ; then point at MOS sprite area

        AND     R0, R0, #&FF            ; Kill the range bits
336
        CMP     R0, #(SwiSpriteOpCallTb_End-SwiSpriteOpCallTb)/4
Neil Turton's avatar
Neil Turton committed
337 338 339
        BCS     BadReasonCode

        ADR     R10, SwiSpriteOpCallTb
Kevin Bracey's avatar
Kevin Bracey committed
340
        ADR     R14, SpriteDispatchReturn ; return address
Neil Turton's avatar
Neil Turton committed
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
        LDR     R11, [R10, R0, LSL #2]  ; load (offset<<8) + flags

        TST     R11, #SSO_ScreenNotAllowed ; if call can specify screen (R2=0)
        TEQEQ   R2, #0                  ; and it is specified
        MOVEQ   R1, #0                  ; then make sprite area ptr 0 as well
        TSTNE   R11, #SSO_NeedsSomething ; or nothing needed anyway
        SpriteOpDispatch EQ             ; then dispatch

        TEQ     R1, #0                  ; else needs sprite area ptr
        ADREQ   R0, SpriteErr_NoWorkSpace ; so if zero then invalid
      [ International
        BLEQ    TranslateError
      ]
        BEQ     %BT20

        TST     R11, #SSO_DangerAreaOp  ; if not a danger area op
        BEQ     %FT32                   ; then skip

        LDR     R9, [WsPtr, #VduSpriteArea] ; else check if sprite area is same
        TEQ     R9, R1
        BEQ     SpriteIsCurrentDest     ; and error if so

32
        TST     R11, #SSO_NeedsSprite   ; if doesn't need sprite
        BNE     %FT33

        TEQ     R0,#SpriteReason_CreateSprite
        BEQ     %FT21

        TEQ     R0,#SpriteReason_ScreenSave
        TEQNE   R0,#SpriteReason_GetSprite
        TEQNE   R0,#SpriteReason_GetSpriteUserCoords

        SpriteOpDispatch NE             ; let it go if we're not interested in it

        LDR     R9,[WsPtr, #Log2BPP]    ; fetch the current bpp

        CMP     R9,#4
        SpriteOpDispatch CC             ; let it go if below 16bpp
22
        CMP     R3,#0
        BNE     %FT34                   ; bang if it has a palette

        SpriteOpDispatch                ; then dispatch

21      ;createsprite. R6=mode number or sprite mode word, or => mode descriptor
        Push    "R0-R3,R14"
        MOV     R0,R6
        MOV     R1,#VduExt_Log2BPP
        SWI     XOS_ReadModeVariable
        MOVCS   R2,#0
        CMP     R2,#4
        Pull    "R0-R3,R14"
        SpriteOpDispatch CC
        B       %BT22

33
        TEQ     R2, #0                  ; if sprite ptr is zero it's a boob
        BEQ     %BT15                   ; so say SpriteDoesntExist

        LDR     R9, [WsPtr, #RetnReg0]
        CMP     R9, #RangeC             ; if not range C then must look up
        BCS     %FT35                   ; sprite name and convert to pt4
        Push    R14
        BL      SpriteCtrlBlk           ; in: R2 -> name; out: R2 -> sprite
        Pull    R14
        BVS     %BT15                   ; no such sprite

35

;medusa note.
;
;On Medusa masks and palettes for 16/32bpp sprites are in a transient state
;Medusa will fault 16/32bpp mask/palette operations, in readiness for the
;introduction of new (more compact) mask/palette formats.
;
;another medusa note.
;
;Mask operations using 1bpp masks on new format sprites are now being included.
;However palettes on 16/32bpp are still not allowed.
;

;amg 12/11/93, sort out the logic here so that palettes on new format sprites
;really do get faulted

;amg 25th May 1994. We now allow palettes on new format sprites of 8bpp
;and below

        ; find the sprite type
430
        Push   "R14"
Neil Turton's avatar
Neil Turton committed
431 432
        LDR    R9,[R2,#spMode]

433
        ANDS   R14,R9,#15<<27           ; get the sprite type
Neil Turton's avatar
Neil Turton committed
434 435
        BEQ    %FT37                    ; t=0 (ie old format)

436 437 438 439 440 441 442 443
        CMP    R14,#SpriteType_RISCOS5<<27 ; if it's a RISC OS 5 sprite mode word
        MOVEQ  R14,R9,LSR #20            ; then get the actual sprite type
        MOVNE  R14,R14,LSR #27
        ANDEQS R14,R14,#127
        MOVEQ  R14,#SpriteType_Substitute ; Panic and treat as 32bpp?

        CMP    R14,#SpriteType_New16bpp ; check sprite type number
        BCC    %FT38                    ; despatch if new format and under 16bpp
Neil Turton's avatar
Neil Turton committed
444 445


446 447
39
        ; so, does it have a palette
Neil Turton's avatar
Neil Turton committed
448 449 450 451 452 453 454
        ADD    R9,R2,#spImage
        LDMIA  R9,{R9,R14}              ; pick up offsets to mask & image
        CMP    R9,R14
        MOVGT  R9,R14                   ; R9->top of palette block
        SUBS   R9,R9,#spPalette         ; R9 = size of palette block
        BEQ    %FT38                    ; no palette, so no error

455
        Pull   "R14"
Neil Turton's avatar
Neil Turton committed
456 457 458 459 460 461 462 463
34
        ADRL    R0, SpriteErr_NoMaskOrPaletteAllowedInThisDepth
        [ International
        BL      TranslateError
        ]
        B       %BT20

37      ;however, until mode selectors work there are some 16/32bpp old modes
464
        Push    "R0-R3"                 ; save context
Neil Turton's avatar
Neil Turton committed
465 466 467 468
        MOV     R0,R9
        MOV     R1,#VduExt_Log2BPP
        SWI     XOS_ReadModeVariable    ; read log2bpp for the sprite's mode
        MOV     R9,R2                   ; and move it for posterity
469
        Pull    "R0-R3"
Neil Turton's avatar
Neil Turton committed
470 471 472 473
        CMP     R9,#4
        BCS     %BT39                   ; log2bpp of 4 = 16bpp, so see if we want to fault it
38
        TST     R11, #SSO_DangerOp      ; if a destructive op
474
        Pull    "R14"
Neil Turton's avatar
Neil Turton committed
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
        BEQ     %FT40

        LDR     R9, [WsPtr, #VduSprite]
        TEQ     R9, R2
        BEQ     SpriteIsCurrentDest     ; then stop him!

40
        TST     R11, #SSO_NeedsSpriteModeData
        SpriteOpDispatch EQ

        Push    "R5-R7, R10, R11, R14"
        BL      SetupSprModeData
        Pull    "R5-R7, R10, R11, R14"
        SpriteOpDispatch VC

        B       %BT30                   ; Invalid spMode field


SSO_ScreenNotAllowed    * 1 :SHL: 0
SSO_NeedsSomething      * 1 :SHL: 1
SSO_NeedsSprite         * 1 :SHL: 2
SSO_NeedsSpriteModeData * 1 :SHL: 3
SSO_DangerOp            * 1 :SHL: 4
SSO_DangerAreaOp        * 1 :SHL: 5

Group1  * SSO_ScreenNotAllowed
Group2  * Group1 + SSO_NeedsSomething
Group3  * Group2 + SSO_NeedsSprite
Group4  * Group3 + SSO_NeedsSpriteModeData
Group5  * SSO_NeedsSomething + SSO_NeedsSprite

SwiSpriteOpCallTb
507 508
        SpriteOpEntry BadReasonCode, Group1
        SpriteOpEntry BadReasonCode, Group1
Neil Turton's avatar
Neil Turton committed
509 510
        SpriteOpEntry ScreenSave, Group1
        SpriteOpEntry ScreenLoad, Group1
511 512 513 514
        SpriteOpEntry BadReasonCode, Group1 ; 4
        SpriteOpEntry BadReasonCode, Group1 ; 5
        SpriteOpEntry BadReasonCode, Group1 ; 6
        SpriteOpEntry BadReasonCode, Group1 ; 7
Neil Turton's avatar
Neil Turton committed
515 516 517 518 519 520 521 522 523 524 525 526 527 528

; The following need valid workspace

        SpriteOpEntry ReadAreaCB, Group2
        SpriteOpEntry ClearSprites, Group2 + SSO_DangerAreaOp   ; *SNew
        SpriteOpEntry LoadSpriteFile, Group2 + SSO_DangerAreaOp
                                                ; *SLoad <filename>
        SpriteOpEntry MergeSpriteFile, Group2 + SSO_DangerAreaOp
                                                ; *SMerge <filename>
        SpriteOpEntry SaveSpriteFile, Group2    ; *SSave <filename>
        SpriteOpEntry ReturnName, Group2
        SpriteOpEntry GetSprite, Group2         ; *SGet <name>
        SpriteOpEntry CreateSprite, Group2
        SpriteOpEntry GetSpriteUserCoords, Group2
529 530 531 532 533 534 535
        SpriteOpEntry BadReasonCode, Group2 ; 17 CheckSpriteArea
        SpriteOpEntry BadReasonCode, Group2 ; 18
        SpriteOpEntry BadReasonCode, Group2 ; 19
        SpriteOpEntry BadReasonCode, Group2 ; 20
        SpriteOpEntry BadReasonCode, Group2 ; 21
        SpriteOpEntry BadReasonCode, Group2 ; 22
        SpriteOpEntry BadReasonCode, Group2 ; 23
Neil Turton's avatar
Neil Turton committed
536 537 538 539 540 541 542 543 544 545 546 547 548 549

; The following need a sprite

        SpriteOpEntry SelectSprite, Group3      ; *SChoose <n> [<m>]
        SpriteOpEntry DeleteSprite, Group3 + SSO_DangerOp       ; *SDelete <n>
        SpriteOpEntry RenameSprite, Group3                      ; *SRename
        SpriteOpEntry CopySprite, Group3                        ; *SCopy
        SpriteOpEntry PutSprite, Group3
        SpriteOpEntry CreateMask, Group3
        SpriteOpEntry RemoveMask, Group3 + SSO_DangerOp
        SpriteOpEntry InsertRow, Group3 + SSO_DangerOp
        SpriteOpEntry DeleteRow, Group3 + SSO_DangerOp
        SpriteOpEntry FlipAboutXAxis, Group3
        SpriteOpEntry PutSpriteUserCoords, Group3
550 551 552 553 554
        SpriteOpEntry BadReasonCode, Group3 ; 35 AppendSprite
        SpriteOpEntry BadReasonCode, Group3 ; 36 SetPointerShape
        SpriteOpEntry BadReasonCode, Group3 ; 37 CreateRemovePalette
        SpriteOpEntry BadReasonCode, Group3 ; 38 CreateRemoveAlpha
        SpriteOpEntry BadReasonCode, Group3 ; 39
Neil Turton's avatar
Neil Turton committed
555 556 557 558 559 560 561 562 563 564 565 566 567

; The following need sprite mode data

        SpriteOpEntry ReadSpriteSize, Group4
        SpriteOpEntry ReadPixelColour, Group4
        SpriteOpEntry WritePixelColour, Group4
        SpriteOpEntry ReadPixelMask, Group4
        SpriteOpEntry WritePixelMask, Group4
        SpriteOpEntry InsertCol, Group4 + SSO_DangerOp
        SpriteOpEntry DeleteCol, Group4 + SSO_DangerOp
        SpriteOpEntry FlipAboutYAxis, Group4 + SSO_DangerOp
        SpriteOpEntry PlotMask, Group4
        SpriteOpEntry PlotMaskUserCoords, Group4
568 569 570 571
        SpriteOpEntry BadReasonCode, Group4 ; 50 PlotMaskScaled
        SpriteOpEntry BadReasonCode, Group4 ; 51 PaintCharScaled
        SpriteOpEntry BadReasonCode, Group4 ; 52 PutSpriteScaled
        SpriteOpEntry BadReasonCode, Group4 ; 53 PutSpriteGreyScaled
Neil Turton's avatar
Neil Turton committed
572
        SpriteOpEntry RemoveLeftHandWastage, Group4
573 574 575 576 577
        SpriteOpEntry BadReasonCode, Group4 ; 55 PlotMaskTransformed
        SpriteOpEntry BadReasonCode, Group4 ; 56 PutSpriteTransformed
        SpriteOpEntry BadReasonCode, Group4 ; 57 InsertDeleteRows
        SpriteOpEntry BadReasonCode, Group4 ; 58 InsertDeleteColumns
        SpriteOpEntry BadReasonCode, Group4 ; 59 pseudo reason used by Wimp
Neil Turton's avatar
Neil Turton committed
578 579 580 581 582 583 584

; The following need (sprite area + sprite) or (anything + 0), meaning screen

        SpriteOpEntry SwitchOutputToSprite, Group5 ; 60
        SpriteOpEntry SwitchOutputToMask, Group5   ; 61
        SpriteOpEntry ReadSaveAreaSize, Group5     ; 62

585 586 587
SwiSpriteOpCallTb_End


Neil Turton's avatar
Neil Turton committed
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
; *****************************************************************************
;
;       SetupSprModeData - Set up registers and variables from the sprite mode
;
;       Internal routine: called by sprite dispatch, CreateHeader
;
; in:   R2 -> sprite
;
; out:  R0-R5 preserved
;       R6 = ReadNColour (for a single screen pixel)
;       R7 = WriteNColour (=R6 except in double pixel modes)
;       R8 = BytesPerChar }
;       R9 = XShftFactor  } calculated from Log2BPC which is BitsPerPix
;       R10 = NPix        }  corrected for double pixel modes
;       R11 = Log2BPC     }
;
;       SprReadNColour..SprLog2BPC setup accordingly
;
;       If error, then RetnReg0 updated

SetupSprModeData ROUT
        Push    R14
        LDR     R11, [R2, #spMode]
        CMP     r11, #&100              ; check for mode selector/new format sprite word
        BCC     %FT05                   ; [it's a mode number so check for known ones]
        TST     r11, #1                 ; if it's a new format sprite word
        BNE     %FT10                   ; then call pushmodeinfo to get info on it
        B       %FT20                   ; else it's a mode selector, which is illegal as a sprite mode word
05
        BranchIfKnownMode R11, %FA10
        Push    "R2-R4"
        MOV     R2, R11
        BL      OfferModeExtensionAnyMonitor
        Pull    "R2-R4"
        BNE     %FT20

10
        MOV     R10, R11
        BL      PushModeInfoAnyMonitor
        BVS     %FT30                   ; if duff new format sprite word, return error

        LDR     R11, [R13, #wkModeFlags]
630
        TST     R11, #ModeFlag_NonGraphic
Neil Turton's avatar
Neil Turton committed
631
        BNE     %FT15                   ; non-graphic mode
632
        STR     R11, [WsPtr, #SprModeFlags]
Neil Turton's avatar
Neil Turton committed
633 634

        LDR     R11, [R13, #wkLog2BPC]                  ; Log2BPC
635
        LDR     R14, [R13, #wkLog2BPP]                  ; Log2BPP
Neil Turton's avatar
Neil Turton committed
636 637

        ADD     R13, R13, #PushedInfoSize
638

Neil Turton's avatar
Neil Turton committed
639 640 641
        MOV     R7, #1
        RSB     R9, R11, #5             ; XShftFactor
        RSB     R10, R7, R7, LSL R9     ; NPix
642
        MOV     R6, R7, LSL R14
Neil Turton's avatar
Neil Turton committed
643
        MOV     R8, R7, LSL R11         ; BytesPerChar
644
        RSB     R6, R7, R7, LSL R6      ; ReadNColour
Neil Turton's avatar
Neil Turton committed
645 646 647 648
        RSB     R7, R7, R7, LSL R8      ; WriteNColour

        Push    R5
        ADD     R5, WsPtr, #SprReadNColour
649
        STMIA   R5, {R6-R11,R14}        ; SprRead..SprLog2BPP
Kevin Bracey's avatar
Kevin Bracey committed
650 651
        CLRV
        Pull    "R5, PC"
Neil Turton's avatar
Neil Turton committed
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677

15
        ADD     R13, R13, #PushedInfoSize
20
        ADRL    R0, SpriteErr_InvalidSpriteMode
      [ International
        BL      TranslateError
      ]
30
        STR     R0, [WsPtr, #RetnReg0]
        SETV
        Pull    pc


; *****************************************************************************

; Blocks for sprite errors

SpriteErr_NoWorkSpace                       MakeErrorBlock Sprite_NoWorkSpace
SpriteErr_NoRoom                            MakeErrorBlock Sprite_NoRoom
SpriteErr_DoesntExist                       MakeErrorBlock Sprite_DoesntExist
SpriteErr_NoSprites                         MakeErrorBlock Sprite_NoSprites
SpriteErr_NotGraphics                       MakeErrorBlock Sprite_NotGraphics
SpriteErr_NotEnoughRoom                     MakeErrorBlock Sprite_NotEnoughRoom
SpriteErr_BadSpriteFile                     MakeErrorBlock Sprite_BadSpriteFile
SpriteErr_NoRoomToMerge                     MakeErrorBlock Sprite_NoRoomToMerge
678
SpriteErr_Bad2ndPtr                         MakeErrorBlock Sprite_Bad2ndPtr
Neil Turton's avatar
Neil Turton committed
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
SpriteErr_InvalidRowOrCol                   MakeErrorBlock Sprite_InvalidRowOrCol
SpriteErr_InvalidHeight                     MakeErrorBlock Sprite_InvalidHeight
SpriteErr_InvalidWidth                      MakeErrorBlock Sprite_InvalidWidth
SpriteErr_NoRoomToInsert                    MakeErrorBlock Sprite_NoRoomToInsert
SpriteErr_SpriteAlreadyExists               MakeErrorBlock Sprite_SpriteAlreadyExists
SpriteErr_InvalidSpriteMode                 MakeErrorBlock Sprite_InvalidSpriteMode
SpriteErr_BadReasonCode                     MakeErrorBlock Sprite_BadReasonCode
SpriteErr_CantInTeletext                    MakeErrorBlock Sprite_CantInTeletext
SpriteErr_InvalidSaveArea                   MakeErrorBlock Sprite_InvalidSaveArea
SpriteErr_SpriteIsCurrentDest               MakeErrorBlock Sprite_SpriteIsCurrentDest
SpriteErr_NoMaskOrPaletteAllowedInThisDepth MakeErrorBlock Sprite_NoMaskOrPaletteAllowedInThisDepth

; *****************************************************************************
;
;       ClearSprites - Clear sprite area (*SNEW)
;
;       External routine + dropped thru to
;

ClearSprites ROUT
        LDR     R2, [R1, #saFirst]
        STR     R2, [R1, #saFree]
        MOV     R2, #0
        STR     R2, [R1,#saNumber]

        LDR     R0, [WsPtr, #RetnReg0]  ; if rangeb or rangec
        CMP     R0, #RangeB
Kevin Bracey's avatar
Kevin Bracey committed
706
        BHS     DoesNowt                ; exit immediately
Neil Turton's avatar
Neil Turton committed
707 708 709 710 711 712 713 714 715 716 717 718

; else its rangea, so drop thru to ...

ClearSpritePtrName ROUT
        MOV     R0, #0
        STR     R0, [WsPtr, #SpChoosePtr]
        STR     R0, [WsPtr, #SpChooseName]
        STR     R0, [WsPtr, #SpChooseName+4]
        STR     R0, [WsPtr, #SpChooseName+8]
        MOV     R0, #13
        STRB    R0, [WsPtr, #SpChooseName+12]   ; *SChoose <null name>
DoesNowt
Kevin Bracey's avatar
Kevin Bracey committed
719
        RETURNVC
Neil Turton's avatar
Neil Turton committed
720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738

; *****************************************************************************
;
;       ReadAreaCB - Read information from sprite area CB into registers
;
;       External routine
;
; in:   R1 -> sprite area
;
; out:  R2 = offset to end of sprite area (ie total size)
;       R3 = number of sprites in area
;       R4 = offset to first sprite
;       R5 = offset to first free word
;

ReadAreaCB ROUT
        LDMIA   R1, {R2,R3,R4,R5}               ; saEnd,saNumber,saFirst,saFree
        ADD     R11, WsPtr, #RetnReg2
        STMIA   R11, {R2,R3,R4,R5}
Kevin Bracey's avatar
Kevin Bracey committed
739
        RETURNVC
Neil Turton's avatar
Neil Turton committed
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 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

; *****************************************************************************
;
;       SelectSprite - Select a named sprite for use by PLOT &E8..&EF
;
;       External routine + called by GetSprite
;
; in:   R2 -> sprite CB
;
; out:  R0, R9..R11 corrupted
;       If not using system sprite area, then R2 -> address of sprite
;

SelectSprite ROUT
        Push    R14
        LDR     R0, [WsPtr, #RetnReg0]          ; if not in system sprite area
        CMP     R0, #RangeB
        STRCS   R2, [WsPtr, #RetnReg2]          ; return the sprite address
        Pull    PC, CS

        STR     R2, [WsPtr, #SpChoosePtr]       ; else store name & address
        ADD     R14, R2, #spName                ; for use by PLOT
        LDMIA   R14, {R9,R10,R11}               ; load 12 bytes of name
        LDR     R14, =SpChooseName
        ADD     R14, R14, WsPtr                 ; RetnReg2 NOT altered, so user
        STMIA   R14, {R9,R10,R11}               ; can't poke the workspace
        Pull    PC

; *****************************************************************************
;
;       ReturnName - Return name of nth sprite in sprite area as a string
;
;       External routine
;
; in:   R1 -> sprite area
;       R2 -> buffer
;       R3 = max buffer length
;       R4 = sprite number (n)
;
; out:  R3 actual string length
;       RetnReg3 updated
;

ReturnName ROUT
        LDR     R5, [R1, #saNumber]     ; check for 1 <= R4 <= saNumber
        CMP     R4, #1
        CMPGE   R5, R4
Kevin Bracey's avatar
Kevin Bracey committed
787
        BGE     %FT05
Neil Turton's avatar
Neil Turton committed
788

Kevin Bracey's avatar
Kevin Bracey committed
789
        ADRL    R0, SpriteErr_DoesntExist ; out of range, so generate error
Neil Turton's avatar
Neil Turton committed
790
      [ International
Kevin Bracey's avatar
Kevin Bracey committed
791 792 793
        Push    "lr"
        BL      TranslateError_VClear
        Pull    "lr"
Neil Turton's avatar
Neil Turton committed
794
      ]
Kevin Bracey's avatar
Kevin Bracey committed
795 796
        STR     R0, [WsPtr, #RetnReg0]
        RETURNVS
Neil Turton's avatar
Neil Turton committed
797

Kevin Bracey's avatar
Kevin Bracey committed
798
05      LDR     R5, [R1, #saFirst]
Neil Turton's avatar
Neil Turton committed
799 800 801 802 803 804 805 806 807 808 809 810 811
        ADD     R5, R5, R1              ; ptr to 1st sprite
10
        SUBS    R4, R4, #1
        LDRNE   R6, [R5, #spNext]       ; if not sprite we want
        ADDNE   R5, R5, R6              ; chain to next one
        BNE     %BT10

        ADD     R5, R5, #spName         ; found sprite, R5 -> name

        SUBS    R3, R3, #1
        MOVLS   R3, #0                  ; if was 0 or 1 then set R3 to 0
        STRLS   R3, [WsPtr, #RetnReg3]
        STREQB  R3, [R2]                ; if was 1 then store 0 terminator
Kevin Bracey's avatar
Kevin Bracey committed
812
        MOVLS   PC, R14                 ; if was 0 or 1 then exit (assume SUB cleared V)
Neil Turton's avatar
Neil Turton committed
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830

        CMP     R3, #SpriteNameSize     ; if length > maximum sprite name len
        MOVHI   R3, #SpriteNameSize     ; then limit to maximum sprite name len

; R3 is now maximum number of characters to store, excluding terminator

        MOV     R6, R2                  ; remember start address
20
        LDRB    R4, [R5], #1            ; load a byte from sprite name
        CMP     R4, #" "                ; if char > " "
        STRHIB  R4, [R2], #1            ; then store character and inc ptr
        SUBHIS  R3, R3, #1              ; and decrement character count
        BHI     %BT20                   ; loop until char<=" " or count expired

        MOV     R4, #0                  ; store terminating 0
        STRB    R4, [R2]
        SUB     R3, R2, R6              ; R3 = no. of characters,
        STR     R3, [WsPtr, #RetnReg3]  ; excluding terminator
Kevin Bracey's avatar
Kevin Bracey committed
831
        RETURNVC                        ; indicate no error
Neil Turton's avatar
Neil Turton committed
832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852

; *****************************************************************************
;
;       RenameSprite - Rename a sprite
;
;       External routine (AlreadyExists is used by CopySprite)
;
; in:   R2 -> sprite
;       R3 -> new name
;

RenameSprite ROUT
        Push    "R2, R14"
        MOV     R2, R3
        BL      GetName                 ; returns name in R9-R11
        BL      SpriteCtrlBlk           ; try to find sprite of that name
        BVC     AlreadyExists
        Pull    "R2, R14"
        ADD     R8, R2, #spName
        STMIA   R8, {R9-R11}
        KillSpChoosePtr                 ; in case it points to renamed sprite
Kevin Bracey's avatar
Kevin Bracey committed
853
        RETURNVC
Neil Turton's avatar
Neil Turton committed
854 855 856 857

AlreadyExists                           ; sprite with new name already exists
        Pull    "R3, R14"
        TEQ     R2, R3                  ; if it's the same one, then exit VC
Kevin Bracey's avatar
Kevin Bracey committed
858
        RETURNVC                        ; (SRename/SCopy fred fred is allowed)
Neil Turton's avatar
Neil Turton committed
859 860 861 862 863 864 865 866

        ADRL    R0, SpriteErr_SpriteAlreadyExists
      [ International
        Push    "lr"
        BL      TranslateError
        Pull    "lr"
      ]
        STR     R0, [WsPtr,#RetnReg0]
Kevin Bracey's avatar
Kevin Bracey committed
867
        RETURNVS
Neil Turton's avatar
Neil Turton committed
868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929

; *****************************************************************************
;
;       CopySprite - Make a copy of a sprite
;
;       External routine
;
; in:   R1 -> sprite area
;       R2 -> sprite
;       R3 -> new name
;

CopySprite ROUT
        Push    "R2, R14"               ; save ptr to sprite to be copied
        MOV     R2, R3
        BL      GetName                 ; returns new name in R9-R11
        BL      SpriteCtrlBlk           ; try to find sprite of that name
        BVC     AlreadyExists           ; [we found one of that name]
        Pull    R2
        LDR     R8, [R1, #saFree]
        ADD     R8, R8, R1              ; address sprite will be copied to
        ADD     R8, R8, #spName         ; address of its name field
        BL      AppendSprite            ; copy it
        STMVCIA R8, {R9-R11}            ; if copy OK, rename it
        Pull    PC                      ; exit with V clear/set appropriately

; *****************************************************************************
;
;       ReadSpriteSize - Read sprite size and other info
;
;       External routine
;
; in:   R2 -> sprite
;
; out:  R1,R2 preserved
;       R3 = width in pixels
;       R4 = height in pixels
;       R5 = 0/1 for solid/transparent
;       R6 = mode sprite was defined in
;
;       RetnReg3..RetnReg6 updated
;

ReadSpriteSize ROUT
        ADD     R3, R2, #spWidth
        LDMIA   R3, {R3,R4,R5,R6}       ; spWidth,spHeight,spLBit,spRBit
        ADD     R4, R4, #1              ; R4 := height in pixels
        ADD     R3, R3, #1              ; R3 := width in words
        RSB     R3, R5, R3, LSL #5      ; convert to bits and sub LH wastage
        SUB     R3, R3, #31             ; subtract RH wastage
        ADD     R3, R3, R6
        LDR     R11, [WsPtr, #SprLog2BPC]
        MOV     R3, R3, LSR R11         ; number of pixels in row
        LDR     R5, [R2, #spImage]
        LDR     R6, [R2, #spTrans]
        SUBS    R5, R5, R6
        MOVNE   R5, #1                  ; if spImage=spTrans then no mask
        LDR     R6, [R2, #spMode]

        ADD     R11, WsPtr, #RetnReg3
        STMIA   R11, {R3-R6}

Kevin Bracey's avatar
Kevin Bracey committed
930
        RETURNVC
Neil Turton's avatar
Neil Turton committed
931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058

; *****************************************************************************
;
;       ReadSpriteWidth - Read width of a sprite
;
;       Internal routine, called by PlotMask, InsertCol, DeleteCol
;
; in:   R2 -> sprite
;
; out:  R0 = sprite width in pixels
;       All other registers preserved
;

ReadSpriteWidth ROUT
        Push    "R4-R6, R14"
        ADD     R0, R2, #spWidth
        LDMIA   R0, {R0,R4,R5,R6}       ; spWidth,spHeight,spLBit,spRBit
        ADD     R0, R0, #1              ; width in words
        RSB     R0, R5, R0, LSL #5
        SUB     R0, R0, #31
        ADD     R0, R0, R6              ; total number of bits in row
        LDR     R5, [WsPtr, #SprLog2BPC]
        MOV     R0, R0, LSR R5          ; number of pixels in row
        Pull    "R4-R6, PC"

; *****************************************************************************
;
;       DeleteSpriteByName
;
;       Internal routine, called by MergeSprite, GetSprite, CreateSprite
;
; in:   R1 -> sprite area
;       R2 -> name of sprite to be deleted
;
; out:  All registers preserved
;

DeleteSpriteByName ROUT
        Push    "R2-R4, R14"
        BL      SpriteCtrlBlk           ; R2: In , SpriteNamePtr
                                        ;     Out, SpriteCBptr
        BLVC    DeleteSprite            ; if found, then delete it
        Pull    "R2-R4, PC"

; *****************************************************************************
;
;       DeleteSprite
;
;       External routine + called by DeleteSpriteByName
;
; in:   R1 -> sprite area
;       R2 -> sprite
;
; out:  All registers preserved
;

DeleteSprite ROUT
        Push    "R0, R3,R4, R14"
        LDR     R3, [R2, #spNext]
        ADD     R3, R3, R2
        LDR     R0, [R1, #saFree]
        ADD     R0, R0, R1
        SUB     R0, R0, R3
        CopyDown R2, R3, R0, R14, R4
        LDR     R3, [R1, #saNumber]     ; decrement sprite count
        SUB     R3, R3, #1
        STR     R3, [R1, #saNumber]
        SUB     R3, R2, R1              ; (R2 points to first free location)
        STR     R3, [R1, #saFree]       ; update saFree

        KillSpChoosePtr                 ;Because the sprites have moved

        Pull    "R0, R3,R4, PC"

; *****************************************************************************
;
;       GetName - Read sprite name into buffer, lower cased, padded to 12 chars
;
;       Internal routine, called by RenameSprite, CopySprite,
;        SpriteCtrlBlk, CreateHeader
;
; in:   R2 -> sprite name (terminated by char <= 32)
;
; out:  Name returned in R9-R11 and NameBuf
;       All other registers preserved
;

GetName ROUT
        Push    "R2-R5, R14"
        ADD     R3, WsPtr, #NameBuf
        MOV     R4, #SpriteNameSize
10
        LDRB    R5, [R2], #1
        uk_LowerCase R5, R14
        CMP     R5, #" "
        STRHIB  R5, [R3], #1
        SUBHIS  R4, R4, #1              ; loop until char<=32 or done 12 chars
        BHI     %BT10

        MOV     R5, #0
        CMP     R4, #0                  ; pad with 0 or more nulls
20
        STRHIB  R5, [R3], #1
        SUBHIS  R4, R4, #1
        BHI     %BT20

        ADD     R9, WsPtr, #NameBuf
        LDMIA   R9, {R9-R11}            ; name returned in R9-R11 and NameBuf

        Pull    "R2-R5, PC"

; *****************************************************************************
;
;       SpriteCtrlBlk - Search for control block of named sprite
;
;       Internal routine, called by sprite dispatch, RenameSprite,
;        CopySprite, DeleteSpriteByName
;
; in:   R1 -> sprite area
;       R2 -> sprite name
;
; out:  V=0 => R2 -> sprite
;       V=1 => sprite not found
;              R2 -> first free byte (this fact not used by anyone yet)
;       All other registers preserved
;

SpriteCtrlBlk ROUT
1059 1060 1061 1062
        Entry   "R3-R11"
        ASSERT  saNumber = 4
        ASSERT  saFirst = 8
        LDMIB   R1, {R4,R5}             ; saNumber, saFirst
Neil Turton's avatar
Neil Turton committed
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
        ADD     R3, R5, R1              ; point to first sprite/free space
        CMP     R4, #0
        BEQ     %FT20                   ; no sprites, exit with R3 pointing
                                        ; at free space and R4=0
        BL      GetName                 ; search name in R9-R11 and NameBuf
10
        LDMIA   R3, {R5, R6,R7,R8}      ; spNext, spName(0..2)
        CMP     R6, R9
        CMPEQ   R7, R10
        CMPEQ   R8, R11                 ; (V:=0 if equal)
        BEQ     %FT30                   ; sprite found

        ADD     R3, R3, R5
        SUBS    R4, R4, #1              ; try next sprite
        BNE     %BT10
20
        SETV                            ; indicate not found
30
        MOV     R2, R3                  ; R2 -> sprite or to free space
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
        EXIT

; As above, but uses source name directly without passing it through GetName
; Name must be word aligned and in correct format!

SpriteCtrlBlkNoGetName
        ALTENTRY
        ASSERT  saNumber = 4
        ASSERT  saFirst = 8
        LDMIB   R1, {R4,R5}             ; saNumber, saFirst
        ADD     R3, R5, R1              ; point to first sprite/free space
        CMP     R4, #0
        BEQ     %BT20                   ; no sprites, exit with R3 pointing
        LDMIA   R2, {R9-R11}
        B       %BT10
Neil Turton's avatar
Neil Turton committed
1097

1098 1099
        LTORG

Neil Turton's avatar
Neil Turton committed
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 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 1162 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
; *****************************************************************************
;
;       InternaliseCoords - Convert from external to internal coords
;                           for sprite plotting
;
;       Internal routine called by PutSpriteUserCoords, PlotMaskUserCoords
;
; in:   R3 = external X coordinate
;       R4 = external Y coordinate
;
; out:  R3 = internal X coordinate
;       R4 = internal Y coordinate
;       R1, R2, R5 preserved
;

InternaliseCoords ROUT
        Push    "R1,R2,R5, R14"
        MOV     R0, R3                  ; put external coordinate in R0,R1
        MOV     R1, R4
        ADD     R7, WsPtr, #GCsX
        LDMIA   R7, {R8,R9}             ; preserve GCsX,GCsY around EIG
        MOV     R2, #4                  ; indicate absolute coords
        BL      EIG
        STMIA   R7, {R8,R9}             ; restore GcsX,GCsY
        MOV     R3, R0                  ; internal coord of plotting point
        MOV     R4, R1
        Pull    "R1,R2,R5, PC"

; *****************************************************************************
;
;       PutSpriteUserCoords - Draw sprite to screen using given ext. coords
;
;       External routine
;
; in:   R1 -> sprite area (not used)
;       R2 -> sprite
;       R3 = X coordinate to plot at
;       R4 = Y coordinate to plot at
;       R5 = GCOL action to be used
;

PutSpriteUserCoords ROUT
        Push    R14
        BL      InternaliseCoords
        Pull    R14
        B       PutSpri20

; *****************************************************************************
;
;       PutSprite - Draw sprite to screen at NewPt
;
;       External routine + PutSpri20 called by PutSpriteUserCoords
;        (also external)
;
; in:   R1 -> sprite area (not used)
;       R2 -> sprite
;       R5 = GCOL action to be used
;

; Values held in Ram
;
; N.B. The ordering of these variables is VERY important
;      rearrange at your peril
;
; Within the 'memory to screen' drawing loop, WsPtr (R12) points at
;  ScrAdr, variables either side being loaded/saved in groups using
;  LDMDB / STMIA / LDMIB
;
;           SPltWidth   }
;           SPltHeight  }
;           SPltScrOff  }
;           SPltMemOff  } LDMDB
; WsPtr ->  SPltScrAdr    } STMIA
;           SPltColCnt    } } LDMIB
;           SPltMemAdr      }
;           SPltShftR       }
;           SPltShftL       }
;
;           SPltMskAdr
;
;           SPltLMask
;           SPltRMask
;
;           SPltzgooPtr
;
;

PutSprite ROUT
        ASSERT  NewPtY = NewPtX +4
        ADD     R3, WsPtr, #NewPtX
        LDMIA   R3, {R3, R4}            ; plot sprite at NewPt(X,Y)
PutSpri20
        GraphicsMode R0
Kevin Bracey's avatar
Kevin Bracey committed
1193 1194
        BNE     PutSpriNotGraphics      ; quit with error if not graphics mode

Neil Turton's avatar
Neil Turton committed
1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215
        Push    "WsPtr, R14"            ; push both so R12,R14 are free for use

        Push    "R2"                    ; save the pointer to the sprite

        BL      GenSpritePlotParmBlk

        Pull    "R11"

        BVS     SpriteOffScreen

        SWI     XOS_RemoveCursors       ; assume no error can occur!

        LDR     R5, [WsPtr, #SPltMemAdr]
        LDR     R6, [WsPtr, #SPltMskAdr]
        TEQ     R6, #0
        BEQ     %FT20

        ADD     R6, R6, R5
        STR     R6, [WsPtr, #SPltMskAdr]

        LDR     R14, [R11, #spMode]
1216 1217 1218 1219 1220 1221 1222 1223 1224
        MOVS    R8,R14,ASR #27          ; check for wide mask
        BMI     PutSpriWideMaskErr
        TEQ     R8,#SpriteType_RISCOS5
      [ NoARMT2
        ANDEQ   R8, R14, #127<<20
        MOVEQ   R8, R8, LSR #20
      |
        UBFXEQ  R8, R14, #20, #7
      ]
Neil Turton's avatar
Neil Turton committed
1225 1226 1227 1228

        ;note: new format 1bpp sprites are thrown at the old routine, since it
        ;will render them faster

1229
        CMP     R8, #2
Neil Turton's avatar
Neil Turton committed
1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243
        BCC     TransPlot               ; it's got transparent bits in it! (
        BCS     NewTransPlot            ; it's got 1bpp transparent bits in it!!!
20

; Plot sprite ignoring transparency mask (if any)


        ADD     R11, WsPtr, #SPltzgooMasks
        LDMIA   R11, {R8-R11}           ; masks for screen access (zgoo..zgee)

        LDR     R2, [WsPtr, #SPltAction]  ; GCOL action
        ADD     WsPtr, WsPtr, #SPltScrAdr ; repoint WsPtr at SPltScrAdr
        LDMIA   WsPtr, {R0-R1,R5-R7}

1244
        TST     R2, #7
Neil Turton's avatar
Neil Turton committed
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261
        BNE     SolPl10                 ; not store, do it slowly

; SimpleCase

SolPlFast10

;       R0    ,R1    ,     R5    ,R6   ,R7   ,(R8  ,R9  ,R10 ,R11 )
;       ScrAdr,ColCnt,     MemAdr,ShftR,ShftL,(zgoo,zgeo,zgoe,zgee)

; Plot the first (leftmost) word

        LDMIA   R5, {R2,R3}
        ADD     R5, R5, #4

        ShiftR  R2,R3, R6,R7            ; shift R3,R2 right R6 places
                                        ; we only need result word R2
        LDR     R4, [WsPtr, #SPltLMask-SPltScrAdr] ; on leftmost word
1262
        AND     R3, R2, R4              ; mask down to just the required pixels
Neil Turton's avatar
Neil Turton committed
1263

1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
 [ AvoidScreenReads
        CMP     R4, #&FFFFFFFF
        LDRNE   R2, [R0]                ; plot 1 word
        BICNE   R2, R2, R4              ; knock out mask bits
        ORRNE   R3, R2, R3              ; and or sprite bits
 |
        LDR     R2, [R0]                ; plot 1 word
        BIC     R2, R2, R4              ; knock out mask bits
        ORR     R3, R2, R3              ; and or sprite bits
 ]
Neil Turton's avatar
Neil Turton committed
1274 1275 1276 1277 1278 1279 1280 1281
        STR     R3, [R0], #4

        SUBS    R1, R1, #1
        BLT     SolPlFast50             ; if all plotted, try next scanline
                                        ; else try for blocks of 7
        SUBS    R1, R1, #7
        BLT     SolPlFast30

1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295
        TEQ     R6, #0                  ; if shift needed, use loop 20
        BNE     SolPlFast20             ; else loop 15

SolPlFast15

;       R0    ,R1         ,R5
;       ScrAdr,ColCnt,    ,MemAdr

        LDMIA   R5!, {R2-R4,R8-R11}     ; read 7 words
        STMIA   R0!, {R2-R4,R8-R11}     ; write 7 words back to screen
        SUBS    R1, R1, #7
        BGE     SolPlFast15
        B       SolPlFast30

Neil Turton's avatar
Neil Turton committed
1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329
SolPlFast20

;       R0    ,R1         ,R5    ,R6   ,R7
;       ScrAdr,ColCnt,    ,MemAdr,ShftR,ShftL

        LDMIA   R5, {R2-R4,R8-R11,R14}  ; 8 words needed, gives 7 after shift
        ADD     R5, R5, #7*4            ; advance source ptr 7 words

        ShiftR  R2,R3, R6,R7            ; shift right R6 bits
        ShiftR  R3,R4, R6,R7            ; we only want result words
        ShiftR  R4,R8, R6,R7            ; R2-R4, R8-R11
        ShiftR  R8,R9, R6,R7
        ShiftR  R9,R10, R6,R7
        ShiftR  R10,R11, R6,R7
        ShiftR  R11,R14, R6,R7

        STMIA   R0!, {R2-R4,R8-R11}     ; write 7 words back to screen
        SUBS    R1, R1, #7
        BGE     SolPlFast20

SolPlFast30                             ; try 1 word at a time
        ADDS    R1, R1, #7

;       R0    ,R1    ,     R5    ,R6   ,R7
;       ScrAdr,ColCnt,     MemAdr,ShftR,ShftL

; If EQ this is rightmost word

SolPlFast40
        LDMIA   R5, {R2,R3}
        ADD     R5, R5, #4

        ShiftR  R2,R3, R6,R7            ; shift R3,R2 right R6 places
                                        ; we only need result word R2
1330
        BEQ     SolPlFast45             ; if rightmost word, jump out.
Neil Turton's avatar
Neil Turton committed
1331 1332 1333
        STR     R2, [R0], #4

        SUBS    R1, R1, #1
1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350
        B       SolPlFast40

SolPlFast45
        LDR     R4, [WsPtr, #SPltRMask-SPltScrAdr]
        AND     R3, R2, R4              ; mask down to just the required pixels

 [ AvoidScreenReads
        CMP     R4, #&FFFFFFFF
        LDRNE   R2, [R0]                ; plot 1 word
        BICNE   R2, R2, R4              ; knock out mask bits
        ORRNE   R3, R2, R3              ; and or sprite bits
 |
        LDR     R2, [R0]                ; plot 1 word
        BIC     R2, R2, R4              ; knock out mask bits
        ORR     R3, R2, R3              ; and or sprite bits
 ]
        STR     R3, [R0], #4
Neil Turton's avatar
Neil Turton committed
1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363

SolPlFast50                             ; now try the next scanline
        LDMDB   WsPtr, {R1,R2,R3,R4}    ; R1   ,R2    ,R3    ,R4
                                        ; Width,Height,ScrOff,MemOff
        ADD     R0, R0, R3
        ADD     R5, R5, R4
        SUBS    R2, R2, #1
        STRGE   R2, [WsPtr, #SPltHeight-SPltScrAdr]
        BGE     SolPlFast10             ; plot next scanline
ComplicatedExit
        SWI     XOS_RestoreCursors
SpriteOffScreen
        Pull    "WsPtr, R14"
Kevin Bracey's avatar
Kevin Bracey committed
1364 1365
        RETURNVC

1366 1367 1368
PutSpriWideMaskErr
        ; Not supported!
        SWI     XOS_RestoreCursors
1369 1370
        Pull    "WsPtr, R14"
PutSpriWideMaskErr2
1371 1372 1373
        ADRL    R0, SpriteErr_InvalidSpriteMode
        B       %FT90

Kevin Bracey's avatar
Kevin Bracey committed
1374 1375
PutSpriNotGraphics
        ADRL    R0, SpriteErr_NotGraphics
1376
90
Kevin Bracey's avatar
Kevin Bracey committed
1377 1378 1379 1380 1381 1382 1383 1384
      [ International
        Push    "lr"
        BL      TranslateError
        Pull    "lr"
      ]
        STR     R0, [WsPtr, #RetnReg0]
        RETURNVS

Neil Turton's avatar
Neil Turton committed
1385 1386 1387

; Complicated case

1388
SolPl10 ROUT
Neil Turton's avatar
Neil Turton committed
1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 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

;       R0    ,R1    ,     R5    ,R6   ,R7   ,R8  ,R9  ,R10 ,R11
;       ScrAdr,ColCnt,     MemAdr,ShftR,ShftL,zgoo,zgeo,zgoe,zgee

; Plot the first (leftmost) word

        LDMIA   R5, {R2,R3}
        ADD     R5, R5, #4

        ShiftR  R2,R3, R6,R7            ; shift R3,R2 right R6 places
                                        ; we only need result word R2

        OrrEor  R3,R2, R10,R11          ; form EOR mask
        OrrEor  R2,R2, R8,R9            ; form OR mask

        LDR     R4, [WsPtr, #SPltLMask-SPltScrAdr] ; on leftmost word
        AND     R2, R2, R4              ; mask down to just the required pixels
        AND     R3, R3, R4

        LDR     R4, [R0]                ; plot 1 word
        OrrEor  R4,R4, R2,R3
        STR     R4, [R0], #4

        SUBS    R1, R1, #1
        BLT     SolPl50                 ; if all plotted, try next scanline
                                        ; else try for blocks of 4
        SUBS    R1, R1, #4
        BLT     SolPl30

SolPl20
        STMIA   WsPtr, {R0,R1}          ; save ScrAdr,ColCnt

;       R0    ,R1         ,R5    ,R6   ,R7   ,R8  ,R9  ,R10 ,R11
;       ScrAdr,ColCnt,    ,MemAdr,ShftR,ShftL,zgoo,zgeo,zgoe,zgee

        LDMIA   R5, {R0-R4}             ; 5 words needed, gives 4 after shift
        ADD     R5, R5, #16             ; advance source ptr 4 words
        STR     R5, [WsPtr, #SPltMemAdr-SPltScrAdr]

        ShiftR  R0,R1, R6,R7            ; shift R4-R0 right R6 bits
        ShiftR  R1,R2, R6,R7            ; we only want result words R3-R0
        ShiftR  R2,R3, R6,R7
        ShiftR  R3,R4, R6,R7

        LDR     R4, [WsPtr]             ; get screen address
        LDMIA   R4, {R4-R7}             ; get 4 screen words

        ORoreorEORoreor R4,R0, R8,R9,R10,R11, R14
        ORoreorEORoreor R5,R1, R8,R9,R10,R11, R14
        ORoreorEORoreor R6,R2, R8,R9,R10,R11, R14
        ORoreorEORoreor R7,R3, R8,R9,R10,R11, R14

        LDR     R0, [WsPtr]             ; screen address
        STMIA   R0!, {R4-R7}            ; write 4 words back to screen
        LDMIB   WsPtr, {R1,R5-R7}       ; reload anything we shat on

        SUBS    R1, R1, #4
        BGE     SolPl20

SolPl30                                  ; try 1 word at a time
        ADDS    R1, R1, #4

;       R0    ,R1    ,     R5    ,R6   ,R7   ,R8  ,R9  ,R10 ,R11
;       ScrAdr,ColCnt,     MemAdr,ShftR,ShftL,zgoo,zgeo,zgoe,zgee

; If EQ this is rightmost word

SolPl40
        LDMIA   R5, {R2,R3}
        ADD     R5, R5, #4

        ShiftR  R2,R3, R6,R7            ; shift R3,R2 right R6 places
                                        ; we only need result word R2
        OrrEor  R3,R2, R10,R11          ; form EOR mask
        OrrEor  R2,R2, R8,R9            ; form OR

        LDREQ   R4, [WsPtr, #SPltRMask-SPltScrAdr] ; if rightmost word,
        ANDEQ   R2, R2, R4              ; mask down to just the
        ANDEQ   R3, R3, R4              ; required pixels

        LDR     R4, [R0]
        OrrEor  R4,R4, R2,R3
        STR     R4, [R0], #4

        SUBS    R1, R1, #1
        BGE     SolPl40

SolPl50                                 ; now try the next scanline
        LDMDB   WsPtr, {R1,R2,R3,R4}    ; R1   ,R2    ,R3    ,R4
                                        ; Width,Height,ScrOff,MemOff
        ADD     R0, R0, R3
        ADD     R5, R5, R4
        SUBS    R2, R2, #1
        STRGE   R2, [WsPtr, #SPltHeight-SPltScrAdr]
        BGE     SolPl10                 ; plot next scanline
        B       ComplicatedExit

; *****************************************************************************
;
;       NewTransPlot - Plot sprite using 1 bpp transparency mask
1489
;       Called with R11 -> sprite, R8 = sprite type
Neil Turton's avatar
Neil Turton committed
1490 1491 1492 1493 1494 1495 1496
;       TransPlot is used for 1bpp new sprites since it will be faster

NewTransPlot ROUT

        ; need to derive: bpp, and 1<<(5-log2bpp)

        ADRL    R0, NSM_bpptable-4
1497
        LDR     R10, [R0, R8, LSL #2]   ; get the log2bpp to R10
Neil Turton's avatar
Neil Turton committed
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 1540 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 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 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 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755

        ;R10=log2bpp, R11=>sprite

        LDR     R8, [R11, #spWidth]      ; words-1

        ADD     R9, R8, #1
        MOV     R9, R9, LSL #2           ; number of bytes per row
        STR     R9, [WsPtr, #SPltMaskRowPtr]

        LDR     R9, [R11, #spRBit]       ; last bit used
        ADD     R9, R9, #1               ; change to number of bits
        MOV     R9, R9, LSR R10          ; number of pixels

        RSB     R0, R10, #5
        MOV     R8, R8, LSL R0           ; number of pixels for full words

        ADD     R8, R8, R9               ; total number of pixels

        ANDS    R9, R8, #&1F
        MOVNE   R9, #4
        BIC     R8, R8, #&1F
        ADD     R9, R9, R8, LSR #3       ; number of bytes per mask row

        STR     R9, [WsPtr, #SPltMaskRowLen]

        LDR     R8, [R11, #spImage]
        LDR     R9, [R11, #spTrans]
        ADD     R8, R8, R11
        ADD     R9, R9, R11

        ;RSB     R0, R10, #5            <- DONE ABOVE

        MOV     R1, #1
        MOV     R2, R1, LSL R0          ; r2 holds number of pixels per word

        MOV     R3, R1, LSL R10         ; r3 holds bits per pixel

        ADD     WsPtr, WsPtr, #SPltScrAdr       ; repoint WsPtr, at SPltScrAdr

        LDMIA   WsPtr, {R0-R1,R5-R7,R14}

        STR     R2, [WsPtr, #SPltPixPerWord-SPltScrAdr]
        STR     R3, [WsPtr, #SPltBPP-SPltScrAdr]

        ; sort out where to begin in 1bpp mask (rewritten Aug '93)

        MOV     LR, R9                  ; LR = mask pointer
        MOV     R3, #0                  ; R3 = mask bit
        CMP     R5, R8                  ; R5=>data to plot, R8=>start of sprite

        BEQ     %FT11                   ; nothing to do, go store R3 & LR
        BCC     %FT13                   ; start is before sprite data

        ;R3, R9, r10, R11 free
        ;R2 comes in holding pix per word

        ;if R6 is non zero the image will be a word early.
        MOV     R9, R5                  ; working copy of pointer within sprite
        CMP     R6, #0
        ADDNE   R9, R9, #4              ; take out the extra word for now

        LDR     R11,[WsPtr, #SPltMaskRowLen-SPltScrAdr] ; bytes per mask row

        SUBS    R10, R9, R8             ; difference in bytes

        LDR     R8,[WsPtr, #SPltMaskRowPtr-SPltScrAdr] ; loaded with bytes per image row
        BEQ     %FT13
14
        ;is it less than a row of data
        CMP     R10, R8
        BCC     %FT12                   ; yes it is

        ;deal with a row (or more of data)
        SUB     R10, R10, R8
        ADD     LR, LR, R11
        B       %BT14

12      ;start point is on this row. subtract 4 from difference and add
        ;pix per word to mask bit/ptr until diff=0
        CMP     R10, #0
        BEQ     %FT13

        SUB     R10, R10, #4

        ADD     R3, R3, R2
        CMP     R3, #32
        SUBCS   R3, R3, #32
        ADDCS   LR, LR, #4
        CMP     R10, #0
        BNE     %BT12

13
        ;deal with R6
        CMP     R6,#0
        BEQ     %FT11

        SUBS    R3, R3, R2                ;subtract pix per word
        ADDMI   R3, R3, #32
        SUBMI   LR, LR, #4                ;deal with going into previous word

11
        STR     R3, [WsPtr, #SPltMaskBit-SPltScrAdr]
        STR     LR, [WsPtr, #SPltMaskPtr-SPltScrAdr]

        ; and save it for the end of row increments
        STR     R3, [WsPtr, #SPltMaskRowBit-SPltScrAdr]
        STR     LR, [WsPtr, #SPltMaskRowPtr-SPltScrAdr]

        ADD     R11, WsPtr, #SPltzgooMasks-SPltScrAdr
        LDMIA   R11, {R8-R11}           ; masks for screen access (zgoo..zgee)

NTrnPl10

;       R0    ,R1    ,     R5    ,R6   ,R7   ,R8  ,R9  ,R10 ,R11,    R14
;       ScrAdr,ColCnt,     MemAdr,ShftR,ShftL,zgoo,zgeo,zgoe,zgee,
;
; As far as possible this is based on the original transplot.
;

; Plot the first (leftmost) word

        BL      getmaskword
        MOV     R2, R3

        BL      getmaskword_noinc
        ShiftR  R2,R3, R6,R7            ; we only need result word R2

        LDMIA   R5, {R3,R4}             ; fetch and shift image
        ADD     R5, R5, #4
        ShiftR  R3,R4, R6,R7            ; shift R4,R3 right R6 places

        OrrEor  R4,R3, R10,R11          ; form EOR mask
        OrrEor  R3,R3, R8,R9            ; form OR mask

        AND     R3, R3, R2              ; clear out any transparent pixels
        AND     R4, R4, R2

        LDR     R2, [WsPtr, #SPltLMask-SPltScrAdr] ; on leftmost word
        AND     R3, R3, R2              ; mask down to just the required pixels
        AND     R4, R4, R2

        LDR     R2, [R0]                ; plot 1 word
        OrrEor  R2,R2, R3,R4
        STR     R2, [R0], #4

        SUBS    R1, R1, #1
        BLT     NTrnPl50                 ; if all plotted, try next scanline
                                        ; else try for blocks of 2
        SUBS    R1, R1, #2
        BLT     NTrnPl30

NTrnPl20
        STMIA   WsPtr, {R0,R1}          ; ScrAdr,ColCnt

;       R0    ,R1         ,R5    ,R6   ,R7   ,R8  ,R9  ,R10 ,R11 ,   R14
;       ScrAdr,ColCnt,    ,MemAdr,ShftR,ShftL,zgoo,zgeo,zgoe,zgee,   MskAdr


        BL     getmaskword
        MOV    R0, R3
        BL     getmaskword
        MOV    R1, R3

        BL     getmaskword_noinc
        MOV    R2, R3
        ShiftR R0,R1, R6,R7
        ShiftR R1,R2, R6,R7             ; aligned mask in R0,R1

        LDMIA  R5, {R2-R4}              ; 3 image words needed, gives 2 after
        ADD    R5, R5, #8               ; shifting
        STR    R5, [WsPtr, #SPltMemAdr-SPltScrAdr]
        ShiftR R2,R3, R6,R7
        ShiftR R3,R4, R6,R7             ; aligned image in R2,R3

        LDR    R4, [WsPtr]              ; screen address
        LDMIA  R4, {R4,R5}              ; 2 screen words

        ORoreorEORoreorMASK R4,R2,R0, R8,R9,R10,R11, R14
        ORoreorEORoreorMASK R5,R3,R1, R8,R9,R10,R11, R14

        LDR    R0, [WsPtr]              ; screen address
        STMIA  R0!, {R4,R5}             ; write 2 words back to screen
        LDMIB  WsPtr, {R1,R5,R6}        ; reload anything we shat on

        SUBS   R1, R1, #2
        BGE    NTrnPl20

NTrnPl30                                 ; try 1 word at a time
        ADDS   R1, R1, #2

;       R0    ,R1    ,     R5    ,R6   ,R7   ,R8  ,R9  ,R10 ,R11
;       ScrAdr,ColCnt,     MemAdr,ShftR,ShftL,zgoo,zgeo,zgoe,zgee

; If EQ this is rightmost word

NTrnPl40

        BL      getmaskword
        MOV     R2, R3

        BL      getmaskword_noinc
        ShiftR  R2,R3, R6,R7    ; shift R3,R2 right R6 places, result in R2

        LDMIA   R5, {R3,R4}     ; fetch and align image
        ADD     R5, R5, #4
        ShiftR  R3,R4, R6,R7    ; shift R4,R3 right R6 places, result in R3

        OrrEor  R4,R3, R10,R11  ; form EOR mask
        OrrEor  R3,R3, R8,R9    ; form OR

        AND     R3, R3, R2      ; clear out transparant pixels
        AND     R4, R4, R2

        LDREQ   R2, [WsPtr, #SPltRMask-SPltScrAdr] ; if rightmost word,
        ANDEQ   R3, R3, R2              ; mask down to just the
        ANDEQ   R4, R4, R2              ; required pixels

        LDR     R2, [R0]
        OrrEor  R2,R2, R3,R4
        STR     R2, [R0], #4

        SUBS    R1, R1, #1
        BGE     NTrnPl40

NTrnPl50
        ; now try the next scanline

        ; BEWARE ... genspriteplotparmblock returns values for memoff and
        ; scroff which take account of alignment of screen and sprite data
        ;
        ; Do not alter the logic below unless you really know what
        ; to expect from this routine!!

        LDR     LR, [WsPtr, #SPltMaskRowPtr-SPltScrAdr]
        LDR     R3, [WsPtr, #SPltMaskRowBit-SPltScrAdr]

        LDR     R2, [WsPtr, #SPltMaskRowLen-SPltScrAdr]

        ADD     LR, LR, R2

        STR     LR, [WsPtr, #SPltMaskPtr-SPltScrAdr]
        STR     R3, [WsPtr, #SPltMaskBit-SPltScrAdr]
        STR     LR, [WsPtr, #SPltMaskRowPtr-SPltScrAdr]
        STR     R3, [WsPtr, #SPltMaskRowBit-SPltScrAdr]

        LDMDB   WsPtr, {R1,R2,R3,R4}    ; R1   ,R2    ,R3    ,R4
                                        ; Width,Height,ScrOff,MemOff

        ADD     R0, R0, R3
        ADD     R5, R5, R4

        SUBS    R2, R2, #1
        STRGE   R2, [WsPtr, #SPltHeight-SPltScrAdr]
        BGE     NTrnPl10                 ; plot next scanline

        SWI     XOS_RestoreCursors

        Pull    "WsPtr, R14"
Kevin Bracey's avatar
Kevin Bracey committed
1756
        RETURNVC
Neil Turton's avatar
Neil Turton committed
1757 1758 1759 1760 1761 1762 1763 1764

; get a mask word without incrementing the pointers

getmaskword_noinc ROUT
        Push    "R4, R5, LR"

        LDR     R4, [WsPtr, #SPltMaskBit-SPltScrAdr]
        LDR     R5, [WsPtr, #SPltMaskPtr-SPltScrAdr]
Kevin Bracey's avatar
Kevin Bracey committed
1765
        BL      getmaskword                             ; preserves flags
Neil Turton's avatar
Neil Turton committed
1766 1767 1768
        STR     R4, [WsPtr, #SPltMaskBit-SPltScrAdr]
        STR     R5, [WsPtr, #SPltMaskPtr-SPltScrAdr]

Kevin Bracey's avatar
Kevin Bracey committed
1769
        LDMFD   R13!,{R4,R5,R15}                        ; must preserve flags
Neil Turton's avatar
Neil Turton committed
1770 1771 1772 1773

; get a mask word, and increment pointers

getmaskword ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1774
        Push    "R2,R4,R5,R6,R7,R8,R14"
1775
        MRS     R8, CPSR
Neil Turton's avatar
Neil Turton committed
1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816

;R6 -> mask
;R7 = bit offset

;return in R3, update R6, R7, restore other registers

        MOV     R3, #0                   ; initial result
        LDR     LR, [WsPtr, #SPltPixPerWord-SPltScrAdr]  ; pixels per word
        LDR     R2, [WsPtr, #SPltBPP-SPltScrAdr]    ; bpp

        LDR     R7, [WsPtr, #SPltMaskBit-SPltScrAdr]
        LDR     R6, [WsPtr, #SPltMaskPtr-SPltScrAdr]

        LDR     R4, [R6]                 ; get the mask word
10
        CMP     R7, #0
        LDREQ   R4, [R6]                 ; fetch a new word if required
        MOV     R5, R4, LSR R7           ; shift desired bit down to bit 0

        MOV     R3, R3, LSR #1           ; shift down the result by one bit
        ORR     R3, R3, R5, LSL #31      ; and put bit 0 in at bit 31

        ; now use an ASR of bpp-1 to finish off
        SUB     R5, R2, #1
        MOV     R3, R3, ASR R5

        ADD     R7, R7, #1               ; next mask bit

        CMP     R7, #32                  ; on to next word ?
        ADDEQ   R6, R6, #4               ; increment mask word pointer
        MOVEQ   R7, #0                   ; bit pointer back to 0
                                         ; but don't fetch new word until it is needed!

        SUBS    LR, LR, #1               ; one pixel done
        BNE     %BT10

        STR     R7, [WsPtr, #SPltMaskBit-SPltScrAdr]
        STR     R6, [WsPtr, #SPltMaskPtr-SPltScrAdr]

        ;result in R3, MaskBit/MaskPtr adjusted

1817
        MSR     CPSR_f, R8
Kevin Bracey's avatar
Kevin Bracey committed
1818
        LDMFD   R13!,{R2,R4,R5,R6,R7,R8,R15} ; must save flags
Neil Turton's avatar
Neil Turton committed
1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946

        LTORG

; *****************************************************************************
;
;       TransPlot - Plot sprite using transparency mask
;

TransPlot
        ADD     R11, WsPtr, #SPltzgooMasks
        LDMIA   R11, {R8-R11}           ; masks for screen access (zgoo..zgee)

        ADD     WsPtr, WsPtr, #SPltScrAdr       ; repoint WsPtr, at SPltScrAdr

        LDMIA   WsPtr, {R0-R1,R5-R7,R14}

TrnPl10

;       R0    ,R1    ,     R5    ,R6   ,R7   ,R8  ,R9  ,R10 ,R11,    R14
;       ScrAdr,ColCnt,     MemAdr,ShftR,ShftL,zgoo,zgeo,zgoe,zgee,   MskAdr

; Plot the first (leftmost) word

        LDMIA   R14, {R2,R3}            ; fetch and shift mask right R6 places
        ADD     R14, R14, #4
        ShiftR  R2,R3, R6,R7            ; we only need result word R2

        LDMIA   R5, {R3,R4}             ; fetch and shift image
        ADD     R5, R5, #4
        ShiftR  R3,R4, R6,R7            ; shift R4,R3 right R6 places
                                        ; we only need result word R3
        OrrEor  R4,R3, R10,R11          ; form EOR mask
        OrrEor  R3,R3, R8,R9            ; form OR mask

        AND     R3, R3, R2              ; clear out any transparent pixels
        AND     R4, R4, R2

        LDR     R2, [WsPtr, #SPltLMask-SPltScrAdr] ; on leftmost word
        AND     R3, R3, R2              ; mask down to just the required pixels
        AND     R4, R4, R2

        LDR     R2, [R0]                ; plot 1 word
        OrrEor  R2,R2, R3,R4
        STR     R2, [R0], #4

        SUBS    R1, R1, #1
        BLT     TrnPl50                 ; if all plotted, try next scanline
                                        ; else try for blocks of 2
        SUBS    R1, R1, #2
        BLT     TrnPl30

TrnPl20
        STMIA   WsPtr, {R0,R1}          ; ScrAdr,ColCnt

;       R0    ,R1         ,R5    ,R6   ,R7   ,R8  ,R9  ,R10 ,R11 ,   R14
;       ScrAdr,ColCnt,    ,MemAdr,ShftR,ShftL,zgoo,zgeo,zgoe,zgee,   MskAdr

        LDMIA  R14, {R0-R2}             ; 3 mask words, gives 2 after shifting
        ADD    R14, R14, #8             ; advance mask ptr 2 words
        ShiftR R0,R1, R6,R7
        ShiftR R1,R2, R6,R7             ; aligned mask in R0,R1

        LDMIA  R5, {R2-R4}              ; 3 image words needed, gives 2 after
        ADD    R5, R5, #8               ; shifting
        STR    R5, [WsPtr, #SPltMemAdr-SPltScrAdr]
        ShiftR R2,R3, R6,R7
        ShiftR R3,R4, R6,R7             ; aligned image in R2,R3

        LDR    R4, [WsPtr]              ; screen address
        LDMIA  R4, {R4,R5}              ; 2 screen words

        ORoreorEORoreorMASK R4,R2,R0, R8,R9,R10,R11, R6
        ORoreorEORoreorMASK R5,R3,R1, R8,R9,R10,R11, R6

        LDR    R0, [WsPtr]              ; screen address
        STMIA  R0!, {R4,R5}             ; write 2 words back to screen
        LDMIB  WsPtr, {R1,R5-R6}        ; reload anything we shat on

        SUBS   R1, R1, #2
        BGE    TrnPl20

TrnPl30                                 ; try 1 word at a time
        ADDS   R1, R1, #2

;       R0    ,R1    ,     R5    ,R6   ,R7   ,R8  ,R9  ,R10 ,R11
;       ScrAdr,ColCnt,     MemAdr,ShftR,ShftL,zgoo,zgeo,zgoe,zgee

; If EQ this is rightmost word

TrnPl40
        LDMIA   R14, {R2,R3}    ; fetch and align trans mask
        ADD     R14, R14, #4
        ShiftR  R2,R3, R6,R7    ; shift R3,R2 right R6 places, result in R2

        LDMIA   R5, {R3,R4}     ; fetch and align image
        ADD     R5, R5, #4
        ShiftR  R3,R4, R6,R7    ; shift R4,R3 right R6 places, result in R3

        OrrEor  R4,R3, R10,R11  ; form EOR mask
        OrrEor  R3,R3, R8,R9    ; form OR

        AND     R3, R3, R2      ; clear out transparant pixels
        AND     R4, R4, R2

        LDREQ   R2, [WsPtr, #SPltRMask-SPltScrAdr] ; if rightmost word,
        ANDEQ   R3, R3, R2              ; mask down to just the
        ANDEQ   R4, R4, R2              ; required pixels

        LDR     R2, [R0]
        OrrEor  R2,R2, R3,R4
        STR     R2, [R0], #4

        SUBS    R1, R1, #1
        BGE     TrnPl40

TrnPl50                                 ; now try the next scanline
        LDMDB   WsPtr, {R1,R2,R3,R4}    ; R1   ,R2    ,R3    ,R4
                                        ; Width,Height,ScrOff,MemOff
        ADD     R0, R0, R3
        ADD     R5, R5, R4
        ADD     R14, R14, R4
        SUBS    R2, R2, #1
        STRGE   R2, [WsPtr, #SPltHeight-SPltScrAdr]
        BGE     TrnPl10                 ; plot next scanline

        SWI     XOS_RestoreCursors

        Pull    "WsPtr, R14"
Kevin Bracey's avatar
Kevin Bracey committed
1947
        RETURNVC
Neil Turton's avatar
Neil Turton committed
1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974

        LTORG

; *****************************************************************************
;
;       PlotMaskUserCoords - Draw a rectangle through a sprite mask
;                            using given external coordinates
;
;       External routine
;
; in:   R1 -> sprite area (not used)
;       R2 -> sprite
;       R3 = X coordinate to plot at
;       R4 = Y coordinate to plot at
;

PlotMaskUserCoords ROUT
        Push    R14
        BL      InternaliseCoords
        Pull    R14
        B       PlotMa20

; *****************************************************************************
;
; PlotNewMask
;
; Version of PlotMask for new 1bpp format sprites
1975 1976 1977 1978
;
; R0 = sprite mode word
; R2 -> sprite
; R10 = bits 27-31 of mode word
Neil Turton's avatar
Neil Turton committed
1979 1980 1981

PlotNewMask ROUT

1982 1983 1984 1985 1986 1987 1988
        TEQ     R10, #SpriteType_RISCOS5
      [ NoARMT2
        ANDEQ   R10, R0, #127<<20
        MOVEQ   R10, R10, LSR #20
      |
        UBFXEQ  R10, R0, #20, #7
      ]
Neil Turton's avatar
Neil Turton committed
1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286
        ADRL    R0, NSM_bpptable-4
        LDR     R10, [R0, R10, LSL #2]          ;get the log2bpp

        ;derive mask row length
        ;r10=log2bpp, r2=>sprite

        LDR     R8, [R2, #spWidth]       ; words-1

        ADD     R9, R8, #1               ; total words for a line of image
        MOV     R9, R9, LSL #2           ; total bytes for a line of image
        STR     R9, [WsPtr, #SPltMaskRowPtr]
                                         ; save it for determining mask start position

        LDR     R9, [R2, #spRBit]        ; last bit used
        ADD     R9, R9, #1               ; change to number of bits
        MOV     R9, R9, LSR R10          ; number of pixels

        RSB     R0, R10, #5
        MOV     R8, R8, LSL R0           ; number of pixels for full words

        ADD     R8, R8, R9               ; total number of pixels

        ANDS    R9, R8, #&1F
        MOVNE   R9, #4
        BIC     R8, R8, #&1F
        ADD     R9, R9, R8, LSR #3       ; number of bytes per mask row

        STR     R9, [WsPtr, #SPltMaskRowLen]

        MOV     R1, #1
        MOV     R0, R1, LSL R0                  ;number of pixels

        MOV     R6, R1, LSL R10                 ;bits per pixel

        STR     R0, [WsPtr, #SPltPixPerWord]
        STR     R6, [WsPtr, #SPltBPP]

        LDR     R0, [R2, #spHeight]
        ADD     R0, R0, R4
        LDR     R10, [WsPtr, #GWTRow]
        Least   R0, R0, R10             ; top scanline within window

        LDR     R10, [WsPtr, #YWindLimit]
        SUB     R0, R10, R0             ; flip Y
        AND     R0, R0, #7
        STR     R0, [WsPtr, #SPltEcfIndx] ; index into Ecf

        ADD     R0, WsPtr, R0, LSL #3
        ADD     R0, R0, #BgEcfOraEor
        STR     R0, [WsPtr, #SPltEcfPtr] ; ptr to ECF for highest row plotted

        ;STR     R2, [WsPtr, #SPltMaskRowPtr] ;temp, to save it

        LDR     R8, [R2, #spImage]
        LDR     R9, [R2, #spTrans]
        ADD     R8, R8, R2
        ADD     R9, R9, R2

        Push    "WsPtr, R14"            ; push both so R12,R14 are free for use
        Push    "R2"

        BL      GenSpritePlotParmBlk

        Pull    "R2"

        BVS     SpriteOffScreen
        SWI     XOS_RemoveCursors       ; assume no error can occur!

        ;LDR     R2, [WsPtr, #SPltMaskRowPtr]  ;recover pointer to sprite

        LDR     R8, [R2, #spImage]            ;offset to image
        LDR     R9, [R2, #spTrans]            ;offset to mask
        ADD     R8, R8, R2                    ;change to address of image
        ADD     R9, R9, R2                    ;change to address of mask

        LDR     R5, [WsPtr, #SPltMemAdr]      ;start memory address to plot
        LDR     LR, [WsPtr, #SPltMskAdr]      ;start mask address to plot
        TEQ     LR, #0                        ;off screen ?
        BEQ     SpriteOffScreen               ;so plot nothing

        ;amg 19/1/94 rip out the original algorithm and replace it with the correct one
        ;used with newtransplot which correctly handles genspriteplotparmblk's oddities

        ;now deal with sprites where we aren't starting
        ;at the beginning....
        LDR     R2, [WsPtr, #SPltPixPerWord]  ;pick up pixels per word

        MOV     LR, R9                        ;save mask address
        MOV     R3, #0                        ;set mask pixel counter to 0
        CMP     R5, R8                        ;memory address to plot from = image address ?
        BEQ     %FT11                         ;yes - no fudging needed
        BCC     %FT13

        MOV     R9, R5                        ;working copy of plot start within sprite
        CMP     R6, #0
        ADDNE   R9, R9, #4                    ;take out the extra word for now

        LDR     R11, [WsPtr, #SPltMaskRowLen] ;bytes per mask row
        SUBS    R10, R9, R8                   ;difference between plot start & sprite start
        LDR     R8, [WsPtr, #SPltMaskRowPtr]  ;bytes per image row
        BEQ     %FT13                         ;no difference

14
        ;is it less than a row of data different ?
        CMP     R10, R8
        BCC     %FT12                         ;yes, it is

        ;deal with whole rows
        SUB     R10, R10, R8                  ;decrease difference by size of image row
        ADD     LR, LR, R11                   ;increase mask pointer by size of mask row
        B       %BT14                         ;and loop until less than a row to do

12      ;start pointer is on this row. reduce the difference and increase the mask start
        ;point until they match

        CMP     R10, #0                       ;check for nothing to do
        BEQ     %FT13

        SUB     R10, R10, #4                  ;reduce image by a word

        ADD     R3, R3, R2                    ;increase mask start pixel by the number of
                                              ;pixels in that word

        CMP     R3, #32
        SUBCS   R3, R3, #32
        ADDCS   LR, LR, #4                    ;get the mask bit back into a word's worth

        CMP     R10, #0                       ;extra test down here to avoid taking two
        BNE     %BT12                         ;branches

13      ;remember R6 ? uncompensate now
        CMP     R6, #0
        BEQ     %FT11

        SUBS    R3, R3, R2                    ;go back by the number of pixels in a word
        ADDMI   R3, R3, #32
        SUBMI   LR, LR, #4                    ;deal with going back into previous mask word

11
        STR     R3, [WsPtr, #SPltMaskBit]     ;starting mask bit to plot
        STR     LR, [WsPtr, #SPltMaskPtr]     ;starting mask word to plot

        ; and save it for the end of row increments
        STR     R3, [WsPtr, #SPltMaskRowBit]
        STR     LR, [WsPtr, #SPltMaskRowPtr]

        STR     LR, [WsPtr, #SPltMskAdr]
        STR     LR, [WsPtr, #SPltMemAdr]

        ADD     WsPtr, WsPtr, #SPltScrAdr ; repoint WsPtr at SPltScrAdr

        LDMIA   WsPtr, {R0-R1,R5-R7}

        LDR     R5, [WsPtr, #SPltMaskPtr-SPltScrAdr]
        LDR     R8, [WsPtr, #SPltEcfPtr-SPltScrAdr]
10
        LDMIA   R8, {R8,R9}             ; ora,eor for this row

;       R0    ,R1    ,     R5    ,R6   ,R7   ,R8 ,R9
;       ScrAdr,ColCnt,     MemAdr,ShftR,ShftL,ora,eor

;       Plot the first (Leftmost) word

        BL      getmaskword
        MOV     R2, R3

        BL      getmaskword_noinc

        ShiftR  R2,R3, R6,R7            ; shift R3,R2 right R6 places
                                        ; we only need result word R2
        LDR     R10, [WsPtr, #SPltLMask-SPltScrAdr] ; on leftmost word
        AND     R2, R2, R10             ; mask down to just the required pixels

        LDR     R4, [R0]                ; plot 1 word
        OrrEorMASK R4,R2, R8,R9, R14
        STR     R4, [R0], #4

        SUBS    R1, R1, #1
        BLT     %FT50                   ; if all plotted, try next scanline
                                        ; else try for blocks of 4
        SUBS    R1, R1, #4
        BLT     %FT30

20
        STMIA   WsPtr, {R0,R1}          ; save ScrAdr,ColCnt

;       R0    ,R1         ,R5    ,R6   ,R7
;       ScrAdr,ColCnt,    ,MemAdr,ShftR,ShftL


        BL     getmaskword
        MOV    R0, R3
        BL     getmaskword
        MOV    R1, R3
        BL     getmaskword
        MOV    R2, R3
        BL     getmaskword
        MOV    R8, R3
        BL     getmaskword_noinc
        MOV    R4,R3
        MOV    R3,R8

        ShiftR  R0,R1, R6,R7            ; shift R4-R0 right R6 bits
        ShiftR  R1,R2, R6,R7            ; we only want result words R3-R0
        ShiftR  R2,R3, R6,R7
        ShiftR  R3,R4, R6,R7

        LDR     R4, [WsPtr]             ; get screen address
        LDMIA   R4, {R8-R11}            ; get 4 screen words

        LDR     R6, [WsPtr, #SPltEcfPtr-SPltScrAdr]
        LDMIA   R6, {R6,R7}             ; ora,eor for this row

        OrrEorMASK R8,R0,  R6,R7, R14   ; Scr:=ScrOR(oraANDmsk)EOR(eorANDmsk)
        OrrEorMASK R9,R1,  R6,R7, R14
        OrrEorMASK R10,R2, R6,R7, R14
        OrrEorMASK R11,R3, R6,R7, R14

        LDR     R0, [WsPtr]             ; screen address
        STMIA   R0!, {R8-R11}           ; write 4 words back to screen
        LDMIB   WsPtr, {R1,R5-R7}       ; reload anything we shat on

        SUBS    R1, R1, #4
        BGE     %BT20

30                                      ; try 1 word at a time
        ADDS    R1, R1, #4

;       R0    ,R1    ,     R5    ,R6   ,R7   ,R8 ,R9
;       ScrAdr,ColCnt,     MemAdr,ShftR,ShftL,ora,eor

; If EQ this is rightmost word

        LDR     R8, [WsPtr, #SPltEcfPtr-SPltScrAdr]
        LDMIA   R8, {R8,R9}             ; ora,eor for this row
        LDR     R10, [WsPtr, #SPltRMask-SPltScrAdr]
40

        BL      getmaskword
        MOV     R2, R3

        BL      getmaskword_noinc
        ShiftR  R2,R3, R6,R7    ; shift R3,R2 right R6 places, result in R2
                                ; we only need result word R2

        ANDEQ   R2, R2, R10     ; if rightmost word, mask down to just the
                                ; required pixels
        LDR     R4, [R0]
        OrrEorMASK R4,R2, R8,R9, R14
        STR     R4, [R0], #4

        SUBS    R1, R1, #1
        BGE     %BT40

50                              ; now try the next scanline
        ; BEWARE ... genspriteplotparmblock returns values for memoff and
        ; scroff which take account of alignment of screen and sprite data
        ;
        ; Do not alter the logic below unless you really know what
        ; to expect from this routine!!

        LDMDB   WsPtr, {R1,R2,R3,R4}    ; R1   ,R2    ,R3    ,R4
                                        ; Width,Height,ScrOff,MemOff


        LDR     LR, [WsPtr, #SPltMaskRowPtr-SPltScrAdr]
        LDR     R3, [WsPtr, #SPltMaskRowBit-SPltScrAdr]

        LDR     R2, [WsPtr, #SPltMaskRowLen-SPltScrAdr]

        ADD     LR, LR, R2

        STR     LR, [WsPtr, #SPltMaskPtr-SPltScrAdr]
        STR     R3, [WsPtr, #SPltMaskBit-SPltScrAdr]
        STR     LR, [WsPtr, #SPltMaskRowPtr-SPltScrAdr]
        STR     R3, [WsPtr, #SPltMaskRowBit-SPltScrAdr]

        LDMDB   WsPtr, {R1,R2,R3,R4}    ; R1   ,R2    ,R3    ,R4
                                        ; Width,Height,ScrOff,MemOff
        ADD     R0, R0, R3

        ADD     R10, WsPtr, #(SPltEcfPtr-SPltScrAdr)

        LDMIA   R10, {R8,R9}    ; EcfPtr,EcfIndx
        ADD     R8, R8, #8      ; step both to next row in Ecf
        ADD     R9, R9, #1
        CMP     R9, #8
        MOVGE   R9, #0          ; it's a wrap!
        SUBGE   R8, R8, #(8*8)
        STMIA   R10, {R8,R9}

        SUBS    R2, R2, #1
        STRGE   R2, [WsPtr, #SPltHeight-SPltScrAdr]
        BGE     %BT10                   ; plot next scanline

        SWI XOS_RestoreCursors

        Pull    "WsPtr, R14"
Kevin Bracey's avatar
Kevin Bracey committed
2287
        RETURNVC
Neil Turton's avatar
Neil Turton committed
2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305

; *****************************************************************************
;
;       PlotMask - Draw a rectangle through a sprite mask
;
;       External routine + PlotMa20 called by PlotMaskUserCoords
;        (also external)
;
; in:   R1 -> sprite area (not used)
;       R2 -> sprite
;

PlotMask ROUT
        ASSERT  NewPtY = NewPtX +4
        ADD     R3, WsPtr, #NewPtX
        LDMIA   R3, {R3, R4}            ; plot sprite at NewPt(X,Y)
PlotMa20
        GraphicsMode R0
Kevin Bracey's avatar
Kevin Bracey committed
2306
        BNE     PutSpriNotGraphics      ; quit with error if not graphics mode
Neil Turton's avatar
Neil Turton committed
2307 2308 2309 2310 2311 2312 2313 2314 2315

        LDR     R5, [WsPtr, #GPLBMD]    ; background GCOL action
        ORR     R5, R5, #8              ; force 'use mask'
        LDR     R10, [R2, #spImage]
        LDR     R11, [R2, #spTrans]
        TEQ     R10, R11                ; spImage=spTrans if no mask
        BEQ     %FT90                   ; so plot a rectangle

        LDR     R0, [R2, #spMode]
2316 2317
        MOVS    R10, R0, ASR #27
        BMI     PutSpriWideMaskErr2
Neil Turton's avatar
Neil Turton committed
2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461
        BNE     PlotNewMask

        LDR     R0, [R2, #spHeight]
        ADD     R0, R0, R4
        LDR     R10, [WsPtr, #GWTRow]
        Least   R0, R0, R10             ; top scanline within window

        LDR     R10, [WsPtr, #YWindLimit]
        SUB     R0, R10, R0             ; flip Y
        AND     R0, R0, #7
        STR     R0, [WsPtr, #SPltEcfIndx] ; index into Ecf

        ADD     R0, WsPtr, R0, LSL #3
        ADD     R0, R0, #BgEcfOraEor
        STR     R0, [WsPtr, #SPltEcfPtr] ; ptr to ECF for highest row plotted

        Push    "WsPtr, R14"            ; push both so R12,R14 are free for use
        BL      GenSpritePlotParmBlk
        BVS     SpriteOffScreen
        SWI     XOS_RemoveCursors       ; assume no error can occur!

        LDR     R5, [WsPtr, #SPltMemAdr]
        LDR     R6, [WsPtr, #SPltMskAdr]
        TEQ     R6, #0
        BEQ     SpriteOffScreen

        ADD     R6, R6, R5
        STR     R6, [WsPtr, #SPltMskAdr]
        STR     R6, [WsPtr, #SPltMemAdr]

        ADD     WsPtr, WsPtr, #SPltScrAdr ; repoint WsPtr at SPltScrAdr

        LDMIA   WsPtr, {R0-R1,R5-R7}
        LDR     R8, [WsPtr, #SPltEcfPtr-SPltScrAdr]
10
        LDMIA   R8, {R8,R9}             ; ora,eor for this row

;       R0    ,R1    ,     R5    ,R6   ,R7   ,R8 ,R9
;       ScrAdr,ColCnt,     MemAdr,ShftR,ShftL,ora,eor

;       Plot the first (Leftmost) word

        LDMIA   R5, {R2,R3}
        ADD     R5, R5, #4

        ShiftR  R2,R3, R6,R7            ; shift R3,R2 right R6 places
                                        ; we only need result word R2
        LDR     R10, [WsPtr, #SPltLMask-SPltScrAdr] ; on leftmost word
        AND     R2, R2, R10             ; mask down to just the required pixels

        LDR     R4, [R0]                ; plot 1 word
        OrrEorMASK R4,R2, R8,R9, R14
        STR     R4, [R0], #4

        SUBS    R1, R1, #1
        BLT     %FT50                   ; if all plotted, try next scanline
                                        ; else try for blocks of 4
        SUBS    R1, R1, #4
        BLT     %FT30

20
        STMIA   WsPtr, {R0,R1}          ; save ScrAdr,ColCnt

;       R0    ,R1         ,R5    ,R6   ,R7
;       ScrAdr,ColCnt,    ,MemAdr,ShftR,ShftL

        LDMIA   R5, {R0-R4}             ; 5 words needed, gives 4 after shift
        ADD     R5, R5, #16             ; advance source ptr 4 words
        STR     R5, [WsPtr, #SPltMemAdr-SPltScrAdr]

        ShiftR  R0,R1, R6,R7            ; shift R4-R0 right R6 bits
        ShiftR  R1,R2, R6,R7            ; we only want result words R3-R0
        ShiftR  R2,R3, R6,R7
        ShiftR  R3,R4, R6,R7

        LDR     R4, [WsPtr]             ; get screen address
        LDMIA   R4, {R8-R11}            ; get 4 screen words

        LDR     R6, [WsPtr, #SPltEcfPtr-SPltScrAdr]
        LDMIA   R6, {R6,R7}             ; ora,eor for this row

        OrrEorMASK R8,R0,  R6,R7, R14   ; Scr:=ScrOR(oraANDmsk)EOR(eorANDmsk)
        OrrEorMASK R9,R1,  R6,R7, R14
        OrrEorMASK R10,R2, R6,R7, R14
        OrrEorMASK R11,R3, R6,R7, R14

        LDR     R0, [WsPtr]             ; screen address
        STMIA   R0!, {R8-R11}           ; write 4 words back to screen
        LDMIB   WsPtr, {R1,R5-R7}       ; reload anything we shat on

        SUBS    R1, R1, #4
        BGE     %BT20

30                                      ; try 1 word at a time
        ADDS    R1, R1, #4

;       R0    ,R1    ,     R5    ,R6   ,R7   ,R8 ,R9
;       ScrAdr,ColCnt,     MemAdr,ShftR,ShftL,ora,eor

; If EQ this is rightmost word

        LDR     R8, [WsPtr, #SPltEcfPtr-SPltScrAdr]
        LDMIA   R8, {R8,R9}             ; ora,eor for this row
        LDR     R10, [WsPtr, #SPltRMask-SPltScrAdr]
40
        LDMIA   R5, {R2,R3}
        ADD     R5, R5, #4

        ShiftR  R2,R3, R6,R7    ; shift R3,R2 right R6 places
                                ; we only need result word R2

        ANDEQ   R2, R2, R10     ; if rightmost word, mask down to just the
                                ; required pixels
        LDR     R4, [R0]
        OrrEorMASK R4,R2, R8,R9, R14
        STR     R4, [R0], #4

        SUBS    R1, R1, #1
        BGE     %BT40

50                              ; now try the next scanline

        LDMDB   WsPtr, {R1,R2,R3,R4}    ; R1   ,R2    ,R3    ,R4
                                        ; Width,Height,ScrOff,MemOff
        ADD     R0, R0, R3
        ADD     R5, R5, R4

        ADD     R10, WsPtr, #(SPltEcfPtr-SPltScrAdr)

        LDMIA   R10, {R8,R9}    ; EcfPtr,EcfIndx
        ADD     R8, R8, #8      ; step both to next row in Ecf
        ADD     R9, R9, #1
        CMP     R9, #8
        MOVGE   R9, #0          ; it's a wrap!
        SUBGE   R8, R8, #(8*8)
        STMIA   R10, {R8,R9}

        SUBS    R2, R2, #1
        STRGE   R2, [WsPtr, #SPltHeight-SPltScrAdr]
        BGE     %BT10                   ; plot next scanline

        SWI XOS_RestoreCursors

        Pull    "WsPtr, R14"
Kevin Bracey's avatar
Kevin Bracey committed
2462
        RETURNVC
Neil Turton's avatar
Neil Turton committed
2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673

; Sprite has no mask or gcol says dont use it, so draw a rectangle

90
        Push    R14
        BL      ReadSpriteWidth         ; on exit R0=width in pixels
        ADD     R5, R3, R0
        MOV     R0, R3                  ; x0
        MOV     R1, R4                  ; y0

        LDR     R3, [R2, #spHeight]
        ADD     R3, R3, R4              ; y1
        SUB     R2, R5, #1              ; x1

        LDR     R4, [WsPtr, #CursorFlags]
        TST     R4, #ClipBoxEnableBit
        BLNE    ClipPlotMask

        ADD     R4, WsPtr, #BgEcfOraEor ; select Bg colour & action
        STR     R4, [WsPtr, #GColAdr]
        B       RectFillB

ClipPlotMask ROUT
        Push    "R0-R7,R10,R11, R14"
        ADD     R10, R13, #2*4          ; R10 -> last point (R2,R3)
        MOV     R11, #2                 ; merge two points
        BL      MergeR11PointsFromR10
        Pull    "R0-R7,R10,R11, PC"

; *****************************************************************************
;
;       GenSpritePlotParmBlk - Generate lots of useful variables to help us
;                              to plot sprite
;
;       Internal routine, called by PutSprite, PlotMask, ScreenLoad
;
; in:   R2 -> sprite
;       R3 = X coordinate to plot at
;       R4 = Y coordinate to plot at
;       R5 = GCOL action
;

GenSpritePlotParmBlk ROUT
        Push    R14
        AND     R5, R5, #&F             ; lose any ECF colour bits
        LDR     R6, [R2, #spImage]
        LDR     R7, [R2,#spTrans]
        SUB     R6, R7, R6              ; offset from Image to Trans mask
                                        ; =0 if no mask
        STR     R5, [WsPtr, #SPltAction] ; save action for simple case spotting
        CMP     R5, #8                  ; if GCOL action < 8
        MOVLT   R6, #0                  ; plot as solid anyway
        STR     R6, [WsPtr, #SPltMskAdr]

        AND     R5, R5, #7
        MOV     R5, R5, LSL #2          ; 4 bits for each
        LDR     R6, =TBscrmasks
        MOV     R6, R6, ROR R5          ; put correct bits in top 4 bits
        MOV     R7, R6, ASR #31         ; set R7 to 0 or -1 on bit 31
        MOV     R6, R6, LSL #1
        MOV     R8, R6, ASR #31         ; set R8 to 0 or -1 on bit 30
        MOV     R6, R6, LSL #1
        MOV     R9, R6, ASR #31         ; set R9 to 0 or -1 on bit 29
        MOV     R6, R6, LSL #1
        MOV     R10, R6, ASR #31        ; set R10 to 0 or -1 on bit 28

        ADD     R6, WsPtr, #SPltzgooMasks
        STMIA   R6, {R7-R10}            ; store zgoo, zgeo, zgoe, zgee

        MOV     R14, R2                 ; leave sprite CB ptr in R14
        MOV     R0, R3                  ; leave X coord in R0
        MOV     R1, R4                  ; leave Y coord in R1

        ADD     R11, R14, #spWidth
        LDMIA   R11, {R2,R3}            ; Width-1, Height-1

        ADD     R4, WsPtr, #GWLCol      ; R4  ,R5  ,R6  ,R7
        LDMIA   R4, {R4,R5,R6,R7}       ; LCol,BRow,RCol,TRow

        SUBS    R5, R5, R1
        MOVLT   R5, #0                  ; no. of rows below window

        ADD     R1, R1, R3              ; Coord of topLH of sprite

        SUBS    R7, R1, R7
        MOVLT   R7, #0                  ; no. of rows above window
        SUB     R1, R1, R7              ; clipped topLH coord

        ADD     R5, R5, R7              ; reduction factor for height

        ADD     R2, R2, #1

        MOV     R8, R14
        LDR     R9, [WsPtr, #CursorFlags]
        TST     R9, #ClipBoxEnableBit
        BLNE    ClipSpritePlot
        MOV     R14, R8

        MUL     R3, R7, R2              ; word offset into sprite image

        Push    "R3,R5"                 ; word offset and height reduction

        Push    R14
        BL      ScreenAddr
        Pull    R14
        MOV     R4, R2                  ; address of top left corner

        LDR     R5, [R14, #spImage]
        ADD     R5, R5, R14             ; address of sprite image

        Pull    R6
        ADD     R5, R5, R6, LSL #2

        LDR     R9, [WsPtr, #XShftFactor]
        LDR     R10, [WsPtr, #NPix]
        LDR     R11, [WsPtr, #Log2BPC]

        BitLOffset R7,R0, R9,R10,R11    ; R7 := bit position to align to
        WordOffset R8,R0, R9,R10,R11    ; R8 := word offset on line

        LDR     R0, [WsPtr, #GWRCol]
        BitROffset R1,R0, R9,R10,R11
        WordOffset R2,R0, R9,R10,R11
        Push    "R1,R2"

        LDR     R0, [WsPtr, #GWLCol]
        BitLOffset R1,R0, R9,R10,R11
        WordOffset R2,R0, R9,R10,R11

        Push    "R1,R2,R8"

        ADD     R11, R14, #spWidth
        LDMIA   R11, {R0,R1,R6,R8}      ; Width-1, Height-1, LBit, RBit

        MOV     R3, #0                  ; offset to next row in sprite

        SUBS    R6, R6, R7              ; no. of bits to shift sprite
                                        ; before plotting
                                        ; use R7 as LBit
        SUBS    R8, R8, R6              ; calculate new RBit
        ADDLT   R8, R8, #32
        ADDLT   R3, R3, #4

        CMP     R8, #32
        SUBGE   R8, R8, #32
        SUBGE   R3, R3, #4

; R9  Offset on line to plot point, R7 LBit
; R11 Offset on line to GWLCol      R10 bit position

        Pull    "R10,R11"
        Pull    R9

        SUBS    R9, R11, R9
        SUBLT   R11, R11, R9

        ADDGT   R4, R4, R9, LSL #2
        ADDGT   R5, R5, R9, LSL #2
        ADDGT   R3, R3, R9, LSL #2

        CMPEQ   R10, R7
        MOVGT   R7, R10

; R10 Offset to GWRCol, R9 bit position
; R11 Offset to RHedge of sprite, R8 RBit

        ADD     R11, R11, R0
        SUB     R11, R11, R3, ASR #2

        Pull    "R9,R10"

        SUBS    R10, R11, R10
        ADDGT   R3, R3, R10, LSL #2

        CMPEQ   R8, R9
        MOVGT   R8, R9

        Pull    R10

        SUBS    R1, R1, R10             ; correct height
        BLT     %FT20

        SUBS    R0, R0, R3, ASR #2      ; corrected width
        BLT     %FT20

        LDR     R2,[WsPtr,#LineLength]
        SUB     R2, R2, #4
        SUB     R2, R2, R0, LSL #2      ; offset to next screen line

        MOV     R9, #&FFFFFFFE          ; RHand partial word mask
        MVN     R9, R9, LSL R8
        MOV     R8, #&FFFFFFFF
        MOV     R8, R8, LSL R7          ; LHand partial word mask

        ANDEQ   R8, R8, R9              ; if width=0, combine LH & RH masks
        MOVEQ   R9, R8

        CMP     R6, #0
        ADDLT   R6, R6, #32             ; correct if neg
        SUBLT   R5, R5, #4
        RSB     R7, R6, #32             ; its complement

        ADD     R11, WsPtr, #SPltWidth
        STMIA   R11, {R0,R1,R2,R3,R4}   ; SPltWidth..SPltScrAdr

        ADD     R11, WsPtr, #SPltColCnt
        STMIA   R11, {R0,R5,R6,R7}      ; SPltColCnt..SPltShftL

        ADD     R11, WsPtr, #SPltMskAdr
        STMIB   R11, {R8,R9}            ; SPltLMask,SPltRMask

Kevin Bracey's avatar
Kevin Bracey committed
2674 2675
        CLRV
        Pull    PC
Neil Turton's avatar
Neil Turton committed
2676 2677

20
Kevin Bracey's avatar
Kevin Bracey committed
2678 2679
        SETV
        Pull    PC
Neil Turton's avatar
Neil Turton committed
2680

2681
        LTORG
Neil Turton's avatar
Neil Turton committed
2682 2683

        END