SprAdjSize 41 KB
Newer Older
Neil Turton's avatar
Neil Turton committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14
; 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.
;
15
; > Sources.SprAdjSize
Neil Turton's avatar
Neil Turton committed
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

;;----------------------------------------------------------------------------
;; AdjustManyRows or Columns
;;----------------------------------------------------------------------------

        MakeSpriteErrorBlock InvalidRowOrCol,,InvRC
        MakeSpriteErrorBlock NoRoomToInsert,,NoIRoom

input_out_of_range
        ADR     R0, ErrorBlock_InvalidRowOrCol
        addr    r1, Title
        BL      copy_error_one          ; Always sets the V bit
        Pull    "R1-R11,PC"

no_room_to_insert
        ADR     R0, ErrorBlock_NoRoomToInsert
        addr    r1, Title
        BL      copy_error_one          ; Always sets the V bit
        Pull    "R1-R11,PC"

; ----------------------------------------------------------
Go_InsertDeleteRows
        Push    "R1-R11,R14"
        Debug   id,"Entry:",R3,R4
;
; see if reason code indicated a sprite name or sprite pointer in R2
        BLVC    findsprite              ; R2 --> sprite
        Pull    "R1-R11,PC",VS
;
; Check for insertion/deletion
46
;
Neil Turton's avatar
Neil Turton committed
47 48 49 50 51 52 53
        CMP     R4, #0
        Pull    "R1-R11,PC",EQ
        BMI     delete_many_rows
        B       insert_many_rows

; ----------------------------------------------------------
delete_many_rows
54
; Updated to work with new format sprites
Neil Turton's avatar
Neil Turton committed
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
;
; Check that the call is trying to start deleting at a row inside the sprite
        RSB     R4, R4, #0
        CMP     R3, #0
        BLT     input_out_of_range
        LDR     R6, [R2, #spHeight]
        ADD     R6, R6, #1
        CMP     R3, R6
        BGE     input_out_of_range
;
; Check that the call is trying to finish deleting at a row inside the sprite
        ADD     R3, R3, R4
        SUBS    R3, R3, #1
        BMI     input_out_of_range
        CMP     R3, R6
        BGE     input_out_of_range
;
; Check for all rows being deleted
        CMP     R4, R6
        BGE     input_out_of_range

        LDR     R5, [R2, #spWidth] ; R5 = sprite width (in words)
        ADD     R5, R5, #1
        MOV     R5, R5, LSL #2     ;   in bytes
        MUL     R0, R4, R5         ; Get length of block to delete
        LDR     R7, [R2, #spImage] ; Get offset to image R7, and mask R8
        LDR     R8, [R2, #spTrans]
        Debug   id,"In range. Details are: (W,H,I,T,size,start)",R5,R6,R7,R8,R0,R3

; Now check for mask
        CMP     R7, R8             ; If they're the same then there is no mask
        BEQ     deleting_rows_no_mask
;
; Delete the mask rows
        ;First, are we new or old format?
        LDR     R9, [R2, #spMode]
        MOVS    R9, R9, LSR #27

93
        BEQ     %FT10
Neil Turton's avatar
Neil Turton committed
94

95 96 97 98 99
        LDR     R5, [R2, #spWidth] ; R5 = mask width - 1 (in words)
        Push    R8
        BL      GetMaskspWidth     ; Change it 'cos we're new format
        Pull    R8
        ADD     R5, R5, #1
Neil Turton's avatar
Neil Turton committed
100

101 102 103 104
        MOV     R5, R5, LSL #2     ; mask row width in bytes
        MUL     R0, R4, R5         ; Get length of block to delete

10      SUB     R9, R6, R3         ; Get address of starting row (from top of sprite)
Neil Turton's avatar
Neil Turton committed
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
        SUB     R9, R9, #1
        MUL     R9, R5, R9
        ADD     R9, R2, R9         ; Add to mask start
        ADD     R9, R8, R9
        LDR     R10, [R1, #saFree] ; Get address of last word to move down
        ADD     R10, R10, R1
        BL      move_memory_down   ; Move the memory from [R9+R0 to R10] down to [R9 to R10-R0]
;
; Account for loss of mask rows in the sprite area block and sprite block
        LDR     R9, [R1, #saFree]  ; Move the 'free space' pointer back by size deleted in bytes
        SUB     R9, R9, R0
        STR     R9, [R1, #saFree]
        LDR     R9, [R2, #spNext]  ; Move offset to next sprite back by size in bytes
        SUB     R9, R9, R0
        STR     R9, [R2, #spNext]

;Finally redo our R5 stuff
        LDR     R5, [R2, #spWidth] ; R5 = sprite width (in bytes)
        ADD     R5, R5, #1
        MOV     R5, R5, LSL #2     ;   in bytes
        MUL     R0, R4, R5         ; Get length of block to delete
;
; Delete the image rows
deleting_rows_no_mask
        SUB     R9, R6, R3         ; Get address of starting row (from top of sprite)
        SUB     R9, R9, #1
        MUL     R9, R5, R9
        ADD     R9, R2, R9         ; Add to image start
        ADD     R9, R7, R9
        LDR     R10, [R1, #saFree] ; Get address of last word to move down
        ADD     R10, R10, R1
        BL      move_memory_down   ; Move the memory from [R9+R0 to R10] down to [R9 to R10-R0]
;
; Account for loss of mask rows in the sprite area block and sprite block
        LDR     R9, [R1, #saFree]  ; Move the 'free space' pointer back by size deleted in bytes
        SUB     R9, R9, R0
        STR     R9, [R1, #saFree]

        CMP     R7, R8             ;Only change the ptr if there is a mask
        LDRNE   R8, [R2, #spTrans] ; Move the mask pointer back by size in bytes
        SUBNE   R8, R8, R0
        STRNE   R8, [R2, #spTrans]

        LDR     R9, [R2, #spNext]  ; Move offset to next sprite back by size in bytes
        SUB     R9, R9, R0
        STR     R9, [R2, #spNext]
;
; Remove rows from data
        Debug   id, "Height, delta",R6,R4
        SUB     R6, R6, #1
        SUB     R6, R6, R4
        STR     R6, [R2, #spHeight]
;
; Exit
159 160
        CLRV
        Pull    "R1-R11,PC"
Neil Turton's avatar
Neil Turton committed
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

; ----------------------------------------------------------
insert_many_rows
; Updated to work with new format sprites
;
; Check that the call is trying to start inserting at a row inside the sprite
        CMP     R3, #0
        BLT     input_out_of_range
        LDR     R6, [R2, #spHeight] ; R6 = sprite height
        ADD     R6, R6, #1
        CMP     R3, R6
        BGT     input_out_of_range
;
        LDR     R5, [R2, #spWidth] ; R5 = sprite width (in bytes)
        ADD     R5, R5, #1
        MOV     R5, R5, LSL #2     ;   in bytes
        MUL     R0, R4, R5         ; Get length of block to insert
        LDR     R7, [R2, #spImage] ; Get offset to image R7, and mask R8
        LDR     R8, [R2, #spTrans]
        LDR     R9, [R1, #saFree]  ; Check that the end of the block after insertion
        ADD     R9, R9, R0
        CMP     R7, R8             ;    (allowing for mask)
        BEQ     little_skip
        LDR     R10, [R2, #spMode]
        MOVS    R10, R10, LSR #27
        ADDEQ   R9, R9, R0         ; Old format, so sprite is same size as image
        BEQ     little_skip

        Push    R5                 ;New format, so we need a quick conversion
        LDR     R5, [R2, #spWidth]
        Push    R8
        BL      GetMaskspWidth
        Pull    R8
        ADD     R5, R5, #1
        MOV     R5, R5, LSL #2
        MUL     R10, R4, R5
        ADD     R9, R9, R10
        Pull    R5                 ;End of quick conversion

200
little_skip
Neil Turton's avatar
Neil Turton committed
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
        LDR     R10, [R1, #saEnd]  ; is before the end of the block
        CMP     R9, R10
        BGT     no_room_to_insert
        Debug   id,"In range. Details are: (W,H,I,T,size,start)",R5,R6,R7,R8,R0,R3
;
; Now check for mask
        CMP     R7, R8             ; If they're the same then there is no mask
        BEQ     inserting_rows_no_mask
;
; Insert the mask rows
;                        Debug   ag,"Eh up, we've got a mask"

        ;First, are we a new or old format sprite?
        LDR     R9, [R2,#spMode]
        MOVS    R9, R9, LSR #27
;                        DebugIf NE,ag,"And it's a new format one at that!"
217
        BEQ     %FT10
Neil Turton's avatar
Neil Turton committed
218

219 220 221 222 223 224 225 226 227 228
        LDR     R5, [R2, #spWidth]
;                        DebugIf NE,ag,"Image width-1 (words) is ",R5
        Push    R8
        BL      GetMaskspWidth     ;Convert it to 1bpp values (words)
        Pull    R8
;                        DebugIf NE,ag,"Mask (1bpp) width-1 (words) is now ",R5
        ADD     R5, R5, #1
        MOV     R5, R5, LSL #2     ;(bytes)
        MUL     R0, R4, R5
10
Neil Turton's avatar
Neil Turton committed
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
;                        Debug   ag,"The grand total of bytes to be moved up by is ",R0
        SUB     R9, R6, R3         ; Get address of starting row (from top of sprite)
        MUL     R9, R5, R9
        ADD     R9, R2, R9         ; Add to mask start
        ADD     R9, R8, R9
;                        Debug   ag,"Moving from ",R9
        LDR     R10, [R1, #saFree] ; Get address of last word to move down
        ADD     R10, R10, R1
;                        Debug   ag,"Moving amount ",R10
        BL      move_memory_up     ; Move the memory from [R9 to R10] up to [R9+R0 to R10+R0]
;
; Account for gain of mask rows in the sprite area block and sprite block
        LDR     R9, [R1, #saFree]  ; Move the 'free space' pointer forward by size inserted in bytes
        ADD     R9, R9, R0
        STR     R9, [R1, #saFree]
        LDR     R9, [R2, #spNext]  ; Move offset to next sprite forward by size in bytes
        ADD     R9, R9, R0
        STR     R9, [R2, #spNext]

;Finally redo our R5 stuff
        LDR     R5, [R2, #spWidth] ; R5 = sprite width (in bytes)
        ADD     R5, R5, #1
        MOV     R5, R5, LSL #2     ;   in bytes
        MUL     R0, R4, R5         ; Get length of block to delete
;                        Debug   ag,"After the rehash of R5, it is (bytes) ",R5
;                        Debug   ag,"and the amount to be moved by is ",R0
;
; Insert the image rows
inserting_rows_no_mask
        SUB     R9, R6, R3         ; Get address of starting row (from top of sprite)
        MUL     R9, R5, R9
        ADD     R9, R2, R9         ; Add to image start
        ADD     R9, R7, R9
        LDR     R10, [R1, #saFree] ; Get address of last word to move up
        ADD     R10, R10, R1
        BL      move_memory_up     ; Move and clear the memory from [R9 to R10] up to [R9+R0 to R10+R0]
;
; Account for loss of mask rows in the sprite area block and sprite block
        LDR     R9, [R1, #saFree]  ; Move the 'free space' pointer forward by size deleted in bytes
        ADD     R9, R9, R0
        STR     R9, [R1, #saFree]

        CMP     R7, R8
        LDRNE   R8, [R2, #spTrans] ; Move the mask pointer forward by size in bytes
        ADDNE   R8, R8, R0
        STRNE   R8, [R2, #spTrans]

        LDR     R9, [R2, #spNext]  ; Move offset to next sprite forward by size in bytes
        ADD     R9, R9, R0
        STR     R9, [R2, #spNext]
;
; Add rows to data
        Debug   id, "Height, delta",R6,R4
        SUB     R6, R6, #1
        ADD     R6, R6, R4
        STR     R6, [R2, #spHeight]
;
; Exit
287 288
        CLRV
        Pull    "R1-R11,PC"
Neil Turton's avatar
Neil Turton committed
289 290 291 292 293 294 295 296 297 298 299 300 301

; ----------------------------------------------------------

Go_InsertDeleteColumns
        Push    "R1-R11,R14"
        Debug   id,"Entry:",R3,R4
;
; see if reason code indicated a sprite name or sprite pointer in R2
        BLVC    findsprite              ; R2 --> sprite
        Pull    "R1-R11,PC",VS

;
; Check for insertion/deletion
302
;
Neil Turton's avatar
Neil Turton committed
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
        CMP     R4, #0
        Pull    "R1-R11,PC",EQ
        BMI     delete_many_columns
        B       insert_many_columns

; ----------------------------------------------------------
delete_many_columns
; Updated to work with new format sprites
;
; Check that the call is trying to start deleting at a column inside the sprite
        RSB     R4, R4, #0
        CMP     R3, #0
        BLT     input_out_of_range
;
; Get log2bpp for the sprite
        Push    "R1-R2"
        LDR     R0, [R2, #spMode]
Robert Sprowson's avatar
Robert Sprowson committed
320
        MOV     R1, #VduExt_Log2BPP
Neil Turton's avatar
Neil Turton committed
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
        SWI     XOS_ReadModeVariable
        Debug   id,"Read mode variable log2bpp for mode:",R2,R0

        ;unknown modes will return CS. It's not safe to proceed from here,
        ;so exit.
        SETV    CS

        MOVVC   R5, R2
        Pull    "R1-R2"
        Pull    "R1-R11,PC",VS

        Push    "R3-R5"                 ; We'll want these later...
;
; Make R3 = left bit to delete, R4 = right bit to delete (if deleting zeroth column
;       then also delete left-hand wastage
        ADD     R4, R3, R4
        MOV     R3, R3, LSL R5          ;       R3 = left-bit of column to delete
338
        MOV     R4, R4, LSL R5          ;       R4 = right-bit
Neil Turton's avatar
Neil Turton committed
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390

        SUB     R4, R4, #1
        LDR     R5, [R2, #spLBit]       ;       Account for left-hand wastage
        CMP     R3, #0                  ;           (but only for R3 if it is non-zero)
        ADDNE   R3, R3, R5
        ADD     R4, R4, R5
        Debug   id, "Deleting from bit to bit ",R3,R4
;
; Check that the call is trying to finish deleting at a column inside the sprite
        LDR     R5, [R2, #spWidth]      ;       Get number of bits to be deleted after the
        SUB     R5, R4, R5, LSL #5      ;           start of the last word in each sprite row
        LDR     R6, [R2, #spRBit]       ;       If it is greater than the last bit used then
        CMP     R5, R6                  ;           an attempt is being made to delete past
        Pull    "R3-R5",GT
        BGT     input_out_of_range      ;           the end of the sprite row
        BLT     not_deleting_rhcolumn

; Check for all columns being deleted
        CMP     R3, #0
        Pull    "R3-R5",EQ
        BEQ     input_out_of_range

; NOTE: The following commented-out chunk of code appears to be superfluous. If preceded by
; a CMP R5,R6 (which might be the expected intention), the routine breaks, messing up when the
; deleted columns include the leftmost column (ie 0). It is left in the source purely to prevent
; someone putting it back in. WT
;        RSBEQ   R6, R6, #31             ;       If it is equal (i.e. deleting the last column)
;        ADDEQ   R4, R4, R6              ;           then delete the right-hand wastage too
;        MOVEQ   R6, #31                 ;       And set RHwastage = 0, for deletion
;        STREQ   R6, [R2, #spRBit]

not_deleting_rhcolumn
        Debug   id, "Deleting from bit to bit ",R3,R4
;
; Okay, now to delete the bits from R3 to R4 in both the image (and the mask)
;
; Delete the columns from the mask

        LDR     R6, [R2, #spTrans]      ;       Check there is a mask
        LDR     R7, [R2, #spImage]
        CMP     R6, R7
        BEQ     %FT99                   ;Branch if no mask

        ;Ok, so we have a mask, but is it new or old format?
        LDR     R5, [R2, #spMode]
        MOVS    R5, R5, LSR #27         ;Isolate the 'tell-tale' bits
        BEQ     %FT98                   ;Skip the next bit if old format

        ;First of all, 'fix' R3, R4, R5 to be 1bpp width
        LDMFD   R13, {R3-R5}            ;       Read but don't pull!
        ADD     R4, R3, R4
;        MOV     R3, R3, LSL #0          ;       R3 = left-bit of column to delete
391
;        MOV     R4, R4, LSL #0          ;       R4 = right-bit
Neil Turton's avatar
Neil Turton committed
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

        SUB     R4, R4, #1
        LDR     R5, [R2, #spLBit]       ;       Account for left-hand wastage
        CMP     R3, #0                  ;           (but only for R3 if it is non-zero)
        ADDNE   R3, R3, R5
        ADD     R4, R4, R5
        Debug   id, "Mask deleting from bit to bit ",R3,R4
98
; First a counter for the rows, and a pointer to the start of the row
        LDR     R5, [R2, #spWidth]      ;load word width of image
        LDR     R8, [R2,#spRBit]
        BL      GetMaskspWidth          ;Work out width of 1bpp mask in words
        MOV     R0, R5                  ;Put it in r0 for the Bl

        LDR     R5, [R2, #spHeight]     ;       Number of rows - 1
        ADD     R6, R6, R2

        BL      delete_columns_from_data ;      Note this returns change in size in R0
        Debug   id,"Change in size after mask op is noted as ",R0
;
; Rearrange the pointers
        LDR     R9, [R2, #spNext]
        SUB     R9, R9, R0
        STR     R9, [R2, #spNext]
        LDR     R9, [R1, #saFree]
        SUB     R9, R9, R0
        STR     R9, [R1, #saFree]
;
; Delete the columns from the image
99
        Pull    "R3-R5"                 ;       Unstack 'em this time
        ADD     R4, R3, R4
        MOV     R3, R3, LSL R5          ;       R3 = left-bit of column to delete
425
        MOV     R4, R4, LSL R5          ;       R4 = right-bit
Neil Turton's avatar
Neil Turton committed
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480

        SUB     R4, R4, #1
        LDR     R5, [R2, #spLBit]       ;       Account for left-hand wastage
        CMP     R3, #0                  ;           (but only for R3 if it is non-zero)
        ADDNE   R3, R3, R5
        ADD     R4, R4, R5
        Debug   id, "Image deleting from bit to bit ",R3,R4

; First a counter for the rows, and a pointer to the start of the row
        LDR     R0, [R2, #spWidth]      ;load word width of image
        LDR     R5, [R2, #spHeight]     ;       Number of rows - 1

        LDR     R6, [R2, #spImage]      ;       Source for deletion
        ADD     R6, R6, R2

        LDR     R8, [R2,#spRBit]
        BL      delete_columns_from_data ;      Note this returns change in size in R0
        Debug   id,"Change in size after image op is noted as ",R0
;
; Rearrange the pointers
        LDR     R8, [R2, #spImage]
        LDR     R9, [R2, #spTrans]
        CMP     R8, R9
        SUBNE   R9, R9, R0
        STRNE   R9, [R2, #spTrans]
        LDR     R9, [R2, #spNext]
        SUB     R9, R9, R0
        STR     R9, [R2, #spNext]
        LDR     R9, [R1, #saFree]
        SUB     R9, R9, R0
        STR     R9, [R1, #saFree]
;
; Completed the image/mask.
; Now adjust number of columns/width in words/LBit/RBit etc.
        LDR     R7, [R2, #spWidth]      ;       R7 = width in bits - 32
        MOV     R7, R7, LSL #5
        LDR     R5, [R2, #spLBit]       ;       R5 = First bit column used
        LDR     R6, [R2, #spRBit]       ;       R6 = Number of bit columns used - 1
        ADD     R6, R6, R7
        ADD     R7, R7, #32             ;       R7 = width in bits
        Debug   id, "Width (bits), LBit, columns used:",R7,R5,R6
        CMP     R3, #0                  ;       Change LBit if deleted first column
        STREQ   R3, [R2, #spLBit]
        Debug   id, "Last bit column before deletion, after LH wastage (perhaps):",R6
        SUB     R8, R4, R3              ;       R8 = number of bit columns deleted
        ADD     R8, R8, #1
        SUB     R6, R6, R8              ;       R6 = last bit column used after columns deleted
        Debug   id, "Last bit column after deletion:",R6
        AND     R8, R6, #31             ;       R8 = RBit
        STR     R8, [R2, #spRBit]
        MOV     R6, R6, LSR #5          ;       R6 = number of words used - 1
        STR     R6, [R2, #spWidth]
        Debug   id, "RBit and Words-1:",R8,R6
;
; Exit
481 482
        CLRV
        Pull    "R1-R11,PC"
Neil Turton's avatar
Neil Turton committed
483
; ----------------------------------------------------------
484
insert_many_columns
Neil Turton's avatar
Neil Turton committed
485 486 487 488 489 490 491 492
;
; Check that the call is trying to start inserting at a column inside the sprite
        CMP     R3, #0
        BLT     input_out_of_range
;
; Get log2bpp for the sprite
        Push    "R1-R2"
        LDR     R0, [R2, #spMode]
Robert Sprowson's avatar
Robert Sprowson committed
493
        MOV     R1, #VduExt_Log2BPP
Neil Turton's avatar
Neil Turton committed
494 495 496 497 498 499 500 501 502 503 504 505
        SWI     XOS_ReadModeVariable
        Debug   id,"Read mode variable log2bpp for mode:",R2,R0
        SETV    CS
        MOVVC   R5, R2
        Pull    "R1-R2"
        Pull    "R1-R11,PC",VS
;
; Make R3 = left bit to start inserting at, R4 = number of bits to insert
        MOV     R3, R3, LSL R5          ;       R3 = left-bit of column to delete
        LDR     R6, [R2, #spLBit]       ;       Account for left-hand wastage
        ADD     R3, R3, R6
        MOV     R4, R4, LSL R5          ;       R4 = number of bits
506
;
Neil Turton's avatar
Neil Turton committed
507 508 509 510 511 512 513 514 515 516 517 518 519 520
; Get change in width in words of the new sprite versus the old sprite
        LDR     R5, [R2, #spRBit]       ;       Check the bit to insert at is inside the sprite
        LDR     R6, [R2, #spWidth]
        ADD     R6, R5, R6, LSL #5      ;       R6 = current right-most bit column + 1
        ADD     R6, R6, #1
        Debug   id,"Insert at bit, Last bit=",r3,r6
        CMP     R3, R6                  ;       If this is before the insertion point then trying
        BGT     input_out_of_range      ;           to insert off the end of the sprite
        ADD     R5, R4, R5              ;       Work out the right-most bit after insertion
        MOV     R5, R5, LSR #5          ;       Find out if it intrudes on a new word or not
        LDR     R6, [R2, #spHeight]     ;       Find total number of words extra required for image
        ADD     R6, R6, #1
        MUL     R5, R6, R5
        LDR     R6, [R2, #spImage]      ;       More room is required if there is also a mask
521
        LDR     R0, [R2, #spTrans]
Neil Turton's avatar
Neil Turton committed
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
        MOV     R7, R5                  ;       No mask, so only 1 times the extra space is needed
        CMP     R6, R0
        BEQ     skip_past               ;       No mask, so skip the next, mask-only, bit.

        ;There is a mask, so more memory needs to be allocated...
        LDR     R8, [R2, #spMode]       ;
        MOVS    R8, R8, LSR #27         ; Ah, but is it a new or old format sprite?
        MOVEQ   R7, R5, LSL #1          ;       Old format, so 2 times the extra space is needed,
        DebugIf EQ,ag,"Old format mask, so R7,R5 are",R7,R5
        BEQ     skip_past               ;       and we can skip the new format gumph

        Push    "R5-R6,R8"              ; Well, it must be new format then!
        Debug   ag,"New format mask."
        LDR     R5, [R2, #spWidth]
        BL      GetMaskspWidth          ; Returns R5=width of 1bpp mask, with R8=new spRBit

        Push    "R1-R2"
        LDR     R0, [R2, #spMode]
Robert Sprowson's avatar
Robert Sprowson committed
540
        MOV     R1, #VduExt_Log2BPP
Neil Turton's avatar
Neil Turton committed
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
        SWI     XOS_ReadModeVariable
        Debug   id,"Read mode variable log2bpp for mode:",R2,R0

        ADD     R5, R8, R4, LSR R2      ; R5 = rightmost bit after insertion
        Pull    "R1-R2"

        MOV     R5, R5, LSR #5          ; Convert it back to words
        LDR     R6, [R2, #spHeight]
        ADD     R6, R6, #1
        MUL     R5, R6, R5              ; R5 = total extra memory required due to mask insertions
        Debug   ag,"Extra space required for mask (words)=",R5
        ADD     R7, R7, R5              ; Add this onto the memory required for the sprite insertions
        Debug   ag,"Total space required (words)=",R7
        Pull    "R5-R6,R8"

;
; Check there is enough spare room for the extra columns
skip_past
        Debug   ag,"Here, R7 = total space required (words) =",R7
        Debug   ag,"      R5 = sprite space requird (words) =",R5
        MOV     R0, R7                  ;       Don't take our R7 value away!
        LDR     R8, [R1, #saFree]       ;       Get last byte required
        ADD     R7, R8, R7, LSL #2
        LDR     R8, [R1, #saEnd]        ;       Check it is inside the sprite area
565
        Debug   id,"NewFree,End=",r7,r8
Neil Turton's avatar
Neil Turton committed
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
        CMP     R7, R8
        BGT     no_room_to_insert       ;       If it isn't then give an error
        MOV     R7, R0                  ;       Grab our R7 value back
;
; Start insertion stage by moving the mask and rest of sprites above expanded image
        Debug   id, "Inserting n bits starting at:",R4,R3
        Debug   id, "Requires extra memory of words:",R5
        MOV     R0, R5, LSL#2           ;       Bytes to move memory up by (ie amount to be inserted in image)
        LDR     R9, [R2, #spTrans]      ;       Memory to move up (start)
        CMP     R9, R6                  ;       If no mask then insert before next sprite
        LDREQ   R9, [R2, #spNext]
        ADD     R9, R9, R2
        LDR     R10, [R1, #saFree]      ;       Memory to move up (end)
        ADD     R10, R10, R1
        BL      move_memory_up
        Debug   ag,"Moved memory up above image insertion point."
;
583
; Now insert columns into the image
Neil Turton's avatar
Neil Turton committed
584 585 586 587 588 589 590 591
        Push    "R1,R5"
        LDR     R5, [R2, #spHeight]
        LDR     R1, [R2, #spWidth]      ;       Required for the insert_columns routine
        Debug   ag,"Inserting columns in data. Height (lines), width (words) =",R5,R1
        BL      insert_columns_in_data  ;       Insert R4 bit columns in image R6 at column R3. No rows-1 = R5
        Debug   ag,"Inserted columns in image."
        Pull    "R1,R5"
;
592
; Adjust the pointers
Neil Turton's avatar
Neil Turton committed
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
        MOV     R9, R7                  ;       Again, keep our R7 safe
        LDR     R7, [R2, #spNext]       ;       Adjust offset to next sprite
        ADD     R7, R7, R0
        STR     R7, [R2, #spNext]
        LDR     R7, [R1, #saFree]       ;       Adjust offset to free block of sprite area
        ADD     R7, R7, R0
        STR     R7, [R1, #saFree]
        LDR     R7, [R2, #spTrans]      ;       If no mask then don't adjust the mask pointer
        Push    R4
        CMP     R6, R7
        BEQ     %FT99                   ;       Skip the next bit if no mask!
        ADD     R6, R7, R0
        STR     R6, [R2, #spTrans]
        MOV     R7, R9                  ;       Again, grab our R7 back
;
; Move other sprites up beyond expanded mask
        Debug   ag,"Well, we'd better do the mask now..."
        Debug   ag,"R7 and R5 are",R7,R5
        SUB     R0, R7, R5              ;       R0 is the amount to move the mask by (total-sprite)
        MOV     R0, R0, LSL #2          ;       Words to bytes conversion
        Debug   ag,"So, amount (bytes) to move mask up by is",R0
        LDR     R9, [R2, #spNext]       ;       Memory to move up (start)
        ADD     R9, R9, R2
        LDR     R10, [R1, #saFree]      ;       Memory to move up (end)
        ADD     R10, R10, R1
        BL      move_memory_up
        Debug   ag,"Moved memory up above mask insertion point."
;
; Insert columns into the mask
        LDR     R7, [R2, #spRBit]       ;       Keep spRBit safe!
        Push    "R1, R7-R8"

        LDR     R5, [R2, #spMode]
        MOVS    R5, R5, LSR #27         ; New or old format sprite?
        LDREQ   R1, [R2, #spWidth]      ;       Old format
        DebugIf EQ,ag,"Old format sprite"
        BEQ     next_bit                ; Skip the next chunk if sprite is old format

        Debug   ag,"New format sprite"
        Push    "R0,R2"
        LDR     R0, [R2, #spMode]
Robert Sprowson's avatar
Robert Sprowson committed
634
        MOV     R1, #VduExt_Log2BPP
Neil Turton's avatar
Neil Turton committed
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
        SWI     XOS_ReadModeVariable
        Debug   id,"Read mode variable log2bpp for mode:",R2,R0
        MOV     R4, R4, LSR R2      ; R4 converted to 1 bpp
        MOV     R3, R3, LSR R2
        Pull    "R0,R2"

        LDR     R5, [R2, #spWidth]
        BL      GetMaskspWidth
        Debug   ag,"spWidth of mask is",R5
        Debug   ag,"spRBit of mask is",R8
        MOV     R1, R5                  ;       Needed for insert_columns routine
        STR     R8, [R2, #spRBit]

next_bit
        LDR     R5, [R2, #spHeight]
        Debug   ag,"just before inserting columns, spWidth of mask is",R1
        Debug   ag,"just before inserting columns, spRBit of mask is",R8
        BL      insert_columns_in_data  ;       Insert R4 bit columns in mask R6 at column R3. No rows-1 = R5
        Debug   ag,"Inserted columns in mask."
        Pull    "R1, R7-R8"
        STR     R7, [R2, #spRBit]
;
657
; Adjust the pointers
Neil Turton's avatar
Neil Turton committed
658 659 660 661 662 663 664
        LDR     R7, [R2, #spNext]       ;       Adjust offset to next sprite
        ADD     R7, R7, R0
        STR     R7, [R2, #spNext]
        LDR     R7, [R1, #saFree]       ;       Adjust offset to free block of sprite area
        ADD     R7, R7, R0
        STR     R7, [R1, #saFree]
;
665
; Exit
Neil Turton's avatar
Neil Turton committed
666 667 668 669 670
99
;
; Change data in the sprite block
        Pull    R4
        LDR     R9, [R2, #spRBit]       ;       Work out right-most bit after insertion
671
        ADD     R9, R4, R9
Neil Turton's avatar
Neil Turton committed
672 673
        LDR     R10, [R2, #spWidth]     ;       R10 = words used -1
        ADD     R10, R10, R9, LSR #5
674
        STR     R10, [R2, #spWidth]
Neil Turton's avatar
Neil Turton committed
675 676
        AND     R9, R9, #31             ;       R9 = last bit used
        STR     R9, [R2, #spRBit]
677 678
        CLRV
        Pull    "R1-R11,PC"
Neil Turton's avatar
Neil Turton committed
679 680 681 682 683 684
; ----------------------------------------------------------
; Move the memory from [R9+R0 to R10] down to [R9 to R10-R0]
move_memory_down
        Push    "R1,R3,R9,R14"
        ADD     R1, R9, R0
        Debug   id,"Moving memory down from,to,finish:",R1,R9,R10
685
01
Neil Turton's avatar
Neil Turton committed
686 687 688 689 690 691 692
        CMP     R1, R10
        BGE     %FT02
        LDR     R3, [R1], #4
        STR     R3, [R9], #4
        B       %BT01
02
        Debug   id,"Moved memory down. From,to,finish are now:",R1,R9,R10
693
        Pull    "R1,R3,R9,PC"
Neil Turton's avatar
Neil Turton committed
694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714

; --------------------------------------------------------
; Move the memory from [R9 to R10] up to [R9+R0 to R10+R0]
move_memory_up
        Push    "R1,R3,R4,R9,R14"
        ADD     R1, R10, R0
        Debug   id,"Moving memory up from,to,finish:",R10,R1,R9
        CMP     r9, r10
01
        LDRCC   R3, [R10, #-4]!
        STRCC   R3, [R1, #-4]!
        CMP     r9, r10
        BCC     %BT01
        MOV     lr, #0
        CMP     r9, r1
02
        STRCC   lr, [r1, #-4]!
        CMP     r9, r1
        BCC     %BT02

        Debug   id,"Moved memory up. From,to,finish are now:",R10,R1,R9
715
        Pull    "R1,R3,R4,R9,PC"
Neil Turton's avatar
Neil Turton committed
716 717 718

; --------------------------------------------------------
; Delete columns from an image/mask
719
delete_columns_from_data
Neil Turton's avatar
Neil Turton committed
720 721 722 723 724 725 726 727 728 729 730
;       R0 = Width of image/mask on entry, change in size on exit
;       R5 = Number of rows in mask
;       R6 = Source for deletion
;       R8 = spRBit
        Push    "R1-R11,R14"
        Push    R0                      ;push it separately
        Push    R8                      ;this separate too
        MOV     R7, R6                  ;       Destination for deletion = source
        Debug  id,"Start of line with R0, start, end, source, dest, R8:",R0,R3,R4,R6,R7,R8
;
; Now for all the rows...
731
01
Neil Turton's avatar
Neil Turton committed
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
;
; Counter to see how many bits have been copied
        MOV     R10, #0
;
; Transfer source to destination until at first word in the row to worry about
        SUBS    R9, R3, #32
02
        BMI     %FT99
        LDR     R8, [R6], #4            ;       Copy whole word from source to destination
        STR     R8, [R7], #4
        ADD     R10, R10, #32           ;       Increase 'bits copied' by 1 word = 32 bits
        SUBS    R9, R9, #32             ;       Decrement counter by 1 word = 32 bits
        B       %BT02                   ;       Loop until all the whole words have been done
;
; Now load the source word at the word including the first column to delete
99
        LDR     R8, [R6]                ;       R8 = word including first column to delete
749
        RSB     R9, R9, #0              ;       R9 = number of unwanted bits in R8
Neil Turton's avatar
Neil Turton committed
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 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824
        MOV     R8, R8, LSL R9          ;       Clear the unwanted bits
        MOV     R8, R8, LSR R9
;
; Skip forward along the source until at the last column to delete
        SUB     R10, R4, R10            ;       R10 = bits left before last bit to copy in row
02
        CMP     R10, #32                ;       If less than 32 then already at the right place
        BLT     %FT99
        ADD     R6, R6, #4              ;       Else move on the source pointer
        SUB     R10, R10, #32           ;           and remove 1 word from the bits left counter
        B       %BT02
;
; Now at the word which includes the last column to delete. Bit twiddling from now on
99
;
; R8 = combination of word including first column to delete and last column to delete
;
        LDR     R11, [R6], #4
        MOV     R11, R11, LSR R10       ;       Remove unwanted bits from the front
        MOV     R11, R11, LSR #1
        RSB     R9, R9, #32             ;       Shift it up past the 32-R9 bits correct in R8
        ORR     R8, R8, R11, LSL R9
;
; If new R9=bottom 5 bits of R3 is bigger than R4 then we need to store this word and move on
        Debug   id,"Middle with R9,R10,R6,R7",R9,R10,R6,R7
        CMP     R9, R10                 ;       Did the last shift shift bits out of the top of R8?
        STRGT   R8, [R7],#4             ;       If so then store the word
        RSBGT   R9, R9, #32             ;          Get bits shifted out into bottom of R8
        MOVGT   R8, R11, LSR R9
        ADDGT   R9, R9, R10             ;          R9 = number of valid bits in R8
        RSBGT   R9, R9, #31
        ADDLE   R9, R9, #31             ;       Else R9 = number of valid bits in R8
        SUBLE   R9, R9, R10
;
; Now we have considered all the words from the start of the row to the one including the last deleted column
        MOV     R10, R4, LSR #5         ;       R10 = number of source words examined - 1
        LDR     R0, [R13, #4]           ;       Read R0 directly off the stack
        Debug   id,"R0 read off stack as ",R0
        MOV     R11, R0                 ;       R11 = number of source words in a row - 1
02
        CMP     R10, R11                ;       While source words examined < source words in a row
        BGE     %FT99
        LDR     R0, [R6], #4            ;       R0 = next source word
        ORR     R8, R8, R0, LSL R9      ;       Add in bottom bits above the R9 valid bits
        STR     R8, [R7], #4            ;       Store R8 in destination
        RSB     R9, R9, #32             ;       New R8 = top R9 bits of R0
        MOV     R8, R0, LSR R9
        RSB     R9, R9, #32
        ADD     R10, R10, #1            ;       Source words examined ++
        B       %BT02                   ;       End while
;
; Finished loop. Any valid bits left over?
99
        LDR     R10, [R13]              ; read R8 off the stack into R10
        Debug   id,"Read R8 off stack into R10 as",R10
        RSB     R10, R10, #31
        CMP     R9, R10
        STRGT   R8, [R7], #4
        Debug   id,"End of line with line, valid bits, data, source, dest:",R5,R9,R8,R6,R7
;
; Loop for all the rows in the sprite image/mask
        SUBS    R5, R5, #1
        BPL     %BT01
;
; Finished all the deletion. Note it must still shuffle down the memory from the end of
; the old image/mask to the end of the new image/mask
        Pull    R8
        Pull    R0                      ;Need to do this to restore stack
        SUB     R0, R6, R7
        MOV     R9, R7
        LDR     R10, [R1, #saFree]
        ADD     R10, R10, R1
        BL      move_memory_down
;
; Return R0 = change in size of data
825
        Pull    "R1-R11,PC"
Neil Turton's avatar
Neil Turton committed
826 827 828
; --------------------------------------------------------
; Insert columns from an image/mask
insert_columns_in_data
829
;       R1 = spWidth
Neil Turton's avatar
Neil Turton committed
830 831 832 833 834
;       R5 = Number of rows in mask/image - 1
;       R6 = Offset from R2 of source for insertion
;       R3 = bit column to insert before
;       R4 = number of columns to insert
;       R0 = change in length of image/mask in bytes after insertion
835
        Push    "R0-R12,R14"
Neil Turton's avatar
Neil Turton committed
836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
        Debug   id,"Entry:R0,R3,R4,R5,R6",R0,R3,R4,R5,R6
;
; Get R6 = source pointer to just after the end of the last row
        ADD     R9, R5, #1
        MOV     R10, R1
        ADD     R10, R10, #1
        MOV     R10, R10, LSL #2        ;R10 = spWidth in bytes
        MLA     R6, R10, R9, R6
;
; Get R7 = destination pointer to just after the end of the finished sprite
        ADD     R6, R6, R2
        ADD     R7, R6, R0
        Debug  id,"Start of line with start,number, source, dest:",R3,R4,R6,R7
;
; Make R3 be the bit column in the destination just after the end of the inserted columns
        ADD     R3, R3, R4
;
; Now for all the rows...
02
;
; R10 = Bit number of start of destination word pointed at [R7-4]. R11 = 32- (new RBit after insertion + 1) = waste bits in word
        MOV     R10, R1
        LDR     R11, [R2, #spRBit]
        ADD     R10, R11, R10, LSL #5
        ADD     R10, R10, R4
        AND     R11, R10, #31
        ADD     R11, R11, #1
        RSB     R11, R11, #32
        BIC     R10, R10, #31
;
; R9 = number of bits in R8 which will be valid
        LDR     R9, [R2, #spRBit]
868
        ADD     R9, R9, #1
Neil Turton's avatar
Neil Turton committed
869 870 871 872 873 874 875 876 877 878 879 880 881
;
; Get the source word on the current line into R8 Its bottom R9 bits are needed/valid.
        Debug   id,"Entry to first loop.source,dest,flag,r9,r10,r11:",R6,R7,R12,R9,R10,R11
01
; Registers have the following meaning at this point:
; r3 = 1st bit column after inserted section
; r4 = width of inserted section
; r6 = source word + 4
; r7 = destination word + 4
; r9 = number of LSBits at r6 unused as yet (1 to 32)
; r10 = 1st column of destination word
; r11 = amount of MSBits to zero out of destination word

882
        LDR     R8, [R6, #-4]!
Neil Turton's avatar
Neil Turton committed
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
;
; Make R8 have its top R9 bits valid, all other bits 0
        RSB     R9, R9, #32             ;       R9 = 32 - x
        MOV     R8, R8, LSL R9          ;       Shifts bits [0,x-1] up to [32-x,32-x+x-1]=[32-x,31]
        RSB     R9, R9, #32             ;       Restore R9
;
; Read in the bits from the word before it, to make all of R8 valid (ignores LH wastage)
        LDR     R14, [R6, #-4]
        ORR     R8, R8, R14, LSR R9
;
; R8 now contains the last 32 bits of pixel bit data from the row of the sprite
; Shift it right to allow for RH wastage in destination sprite
        MOV     R8, R8, LSR R11
;
; If we have shifted out some of this word then move source
; pointer forward again to reread this word next time
        ADD     R9, R9, R11
        CMP     R9, #32
        ADDGT   R6, R6, #4              ;       Have shifted R14-32 bits out. Hence move source pointer back
        SUBGT   R9, R9, #32             ;           so we reread it next time.
;
; Loop until we have got a word which has some bits of inserted columns in it
        CMP     R3, R10
        STRLE   R8, [R7, #-4]!
        SUBLE   R10, R10, #32
        MOVLE   R11, #0
909
        BLE     %BT01
Neil Turton's avatar
Neil Turton committed
910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 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
        Debug   id,"First loop complete.source,dest,flag,r10,R3,R9:",R6,R7,R12,R10,R3,R9

; Registers have the following meaning at this point:
; r3 = 1st bit column after inserted section
; r4 = width of inserted section
; r6 = source word
; r7 = destination word
; r8 = 32 source bits extracted and ready to use from previous step aligned for destination
; r9 = number of LSBits at r6 unused as yet (1 to 32)
; r10 = 1st column of destination word

        ; Mask off bottom (r3 AND 31) bits for hole
        ANDS    r14, r3, #31
        MOVEQ   r14, #32
        MOV     r8, r8, LSR r14
        MOV     r8, r8, LSL r14

        ; Move back a word if all of this word has been masked off
        ADD     r9, r9, r14
        CMP     r9, #32
        ADDGT   r6, r6, #4

        ; Remove the bits which have been blanked from the number of bits to insert
        SUB     r14, r4, r14

        ADD     r14, r14, #32
        B       %FT03

01
        STR     R8, [R7, #-4]!          ;       Store another word
        MOV     R8, #0
        SUB     R10, R10, #32
03
        SUBS    R14, R14, #32           ;       Decrease counter of bits inserted
        BGT     %BT01

        SUB     r14, r3, r4             ; start column of insertion
        ANDS    r14, r14, #31           ; distance into source word

        ; If extracts at least a bit from source word then do so
        RSBNE   r14, r14, #32
        LDRNE   r11, [r6, #-4]!
        MOVNE   r11, r11, LSL r14
        ORRNE   r8, r8, r11, LSR r14

        ; Store it away
        STR     r8, [r7, #-4]!
        SUBS    r10, r10, #32

; Keep copying words of data until we have finished the row
01
        BLT     %FT99
        LDR     R8, [R6, #-4]!
        STR     R8, [R7,#-4]!
        SUBS    R10, R10, #32
        B       %BT01
;
; Finished a row, so loop for all rows
968
99
Neil Turton's avatar
Neil Turton committed
969 970 971 972 973 974
        Debug   id,"Finished Row with source,dest:",R5,R6,R7
        SUBS    R5, R5, #1
        BPL     %BT02
;
; Finished all the rows. Exit time.
        Debug   id,"Finished the rows with source,dest:",R6,R7
975
        Pull    "R0-R12,PC"
Neil Turton's avatar
Neil Turton committed
976 977 978 979 980 981 982 983 984 985 986 987 988


; *****************************************************************************
;
;       GetMaskspWidth - convert spWidth for data to spWidth for mask (1bpp masks)
;
;   NOTE: This routine should be identical to the same routine in VduGrafH except it does
;         not return the updated PSR
;
;       Internal routine.
;
; in:   R5 = spWidth (ie width in words-1)
;       (expects R2->sprite)
989
;
Neil Turton's avatar
Neil Turton committed
990 991 992 993
; out:  R5 = spWidth (words -1) for mask data
;       R8 = Last bit (spRBit) used in mask data

; should only be called for new format sprites, but will cope with old too
994

Neil Turton's avatar
Neil Turton committed
995 996 997
GetMaskspWidth ROUT
        Push    "R0, LR"
        Debug   ag,"Entered GetMaskspWidth with R5,R8",R5,R8
998

Neil Turton's avatar
Neil Turton committed
999 1000
        LDR     LR, [R2, #spMode]       ; fetch the sprite mode
        MOVS    LR, LR, LSR #27         ; isolate the sprite type and test for =0
1001 1002 1003

        Pull    "R0, PC",EQ         ; if an old format sprite, return R5 unchanged

Neil Turton's avatar
Neil Turton committed
1004 1005 1006
        ; treat any T>max sprites as 32bpp
        CMP     LR, #SpriteType_MAX
        MOVCS   LR, #SpriteType_Substitute
1007

Neil Turton's avatar
Neil Turton committed
1008
        ; bugfix 9/8/93: get log2bpp this way
1009 1010
        ADRL    R0, NSM_bpptable
        LDRB    LR, [R0, LR]            ; get the log2bpp to LR
1011

Neil Turton's avatar
Neil Turton committed
1012 1013 1014
        RSB     LR, LR, #5              ; and change to 5-log2bpp

        MOV     R5, R5, LSL LR          ; number of pixels for full words
1015

Neil Turton's avatar
Neil Turton committed
1016
        RSB     LR, LR, #5              ; now switch back to log2bpp
1017
        LDR     R0, [R2, #spRBit]
Neil Turton's avatar
Neil Turton committed
1018 1019
        ADD     R0, R0, #1
        ADD     R5, R5, R0, LSR LR
1020

Neil Turton's avatar
Neil Turton committed
1021 1022 1023 1024 1025 1026 1027
        ANDS    LR, R5, #&1F            ; fit exactly in a number of words ?
        SUB     R8, LR, #1              ; alter the last bit used for the mask data
                                        ; fix bug MED-01130....
        AND     R8, R8, #&1F            ; ....bring back into range 00-1F (may be -1 here)
        MOVNE   LR, #1                  ; if not, add an extra word
        ADD     R5, LR, R5, LSR #5      ; add the whole number of words
        SUB     R5, R5, #1              ; returns as words-1
1028

Neil Turton's avatar
Neil Turton committed
1029 1030
        Debug   ag,"Left GetMaskspWidth with R5,R8",R5,R8

1031
        Pull    "R0, PC"
Neil Turton's avatar
Neil Turton committed
1032 1033

NSM_bpptable
1034 1035 1036 1037
        ; note, yes - I know this could be type-1, but at some point some new type
        ; will break the relationship so it's a table from day 1 to cope with this
        DCB     99,  0, 1, 2,  3,   4,   5
        ;    T= 0    1  2  3   4    5    6
Robert Sprowson's avatar
Robert Sprowson committed
1038
        ; cols= old, 2, 4, 16, 256, 32k, 16M
1039
        ALIGN
Neil Turton's avatar
Neil Turton committed
1040 1041

        END