SprTrans 85.1 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.
;
Robert Sprowson's avatar
Robert Sprowson committed
15
; > Sources.SprTrans
16

Neil Turton's avatar
Neil Turton committed
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
 ^ 0,SP
trns_spr_xcoords                #       16      ;       Four x coordinates
trns_spr_ycoords                #       16      ;       Four y coordinates
trns_comp_spr_left              #       4       ;       Sprite left hand edge (bottom 16 bits)
trns_comp_spr_start             #       4       ;       Sprite start (accounting for internal coord block top)
trns_comp_spr_byte_width        #       4       ;       Sprite byte width << (3-sprite bpp)
trns_comp_spr_height            #       4       ;       Sprite height (top 16 bits) and right hand edge (bottom 16)
trns_comp_spr_ttr               #       4       ;       Translation table (if required)
trns_comp_spr_masko             #       4       ;       Sprite mask offset from image << (3-sprite bpp)
trns_comp_ecf_ora               #       4       ;       ECF OR word
trns_comp_ecf_eor               #       4       ;       ECF EOR word
trns_codebuffer                 #       4       ;       Pointer to codebuffer
trns_spr_X_x0_y                 #       4       ;       Sprite X,Y at top coordinate of area
trns_spr_Y_x0_y                 #       4       ;            in 16.16 fixed point
trns_spr_inc_X_x                #       4       ;       Sprite increments
trns_spr_inc_Y_x                #       4       ;          ( change induced by single
trns_spr_inc_Y_y                #       4       ;            increments in screen x,y on
trns_spr_inc_X_y                #       4       ;            sprite X,Y )
trns_spr_lineptr                #       4       ;       Line to output onto
trns_spr_edgeblock              #       6*4*4   ;       Edge blocks, in format as below
trns_spr_edgeblock_end          #       4*6     ;        -1, to denote end of edge block
trns_ecf_ptr                    #       4       ;       Ecf pointer
trns_masking_word               #       4       ;       Masking word for > eight bit per pixel
trns_comp_mask_offset           #       4       ;       used to point at 1bpp mask data
trns_comp_spr_mask_width        #       4       ;       1bpp mask equivalent of spr_width
trns_comp_mask_base             #       4       ;       1bpp mask adjustment to mask data
Neil Turton's avatar
Neil Turton committed
43
trns_spr_vars_end               *       :INDEX:@
Neil Turton's avatar
Neil Turton committed
44 45 46 47 48 49 50 51 52 53 54

; The edge blocks are stored in a similar fashion to Draw Quick Fill, and the code is mainly a copy
; of that. The actual layout of the blocks is as follows:
;   Offset 0  : Flag word. Top two bits specify direction of line in the X-axis (01=positive,1x=negative)
;                          Bottom two bits specify whether edge is active (01), not yet active (00), or dead (11)
;      The next 5 words are dependent on the flags. For active edges:
;   Offset 4  : Lower Y coordinate (in 256ths pixels, bottom of screen is 0) of edge. The line is deactivated
;                 after reaching this Y coordinate
;   Offset 8  : ABS(deltaX) for the line, in 256ths of a pixel
;   Offset 12 : ABS(deltaY) for the line, in 256ths of a pixel
;   Offset 16 : Bresenham error value for the pixel
Neil Turton's avatar
Neil Turton committed
55
;   Offset 20 : Current X coordinate of the point (in pixels)
Neil Turton's avatar
Neil Turton committed
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
;       For inactive edges:
;   Offset 4  : Lower X coordinate (256ths of pixel)
;   Offset 8  : Lower Y coordinate
;   Offset 12 : Upper X coordinate
;   Offset 16 : Upper Y coordinate
trns_activated          *       2_0001
trns_deactivated        *       2_0010


trns_xsize              RN      0 ; Top 16 bits only.           Used throughout the compiled loop
trns_spr_left           RN      0 ; Bottom 16 bits only.        Used throughout the compiled loop
trns_scr_lx             RN      0 ;                             Used outside the loop
trns_spr_start          RN      1 ;                             Used throughout the loop
trns_scr_rx             RN      1 ;                             Used outside the loop
trns_offset             RN      2 ;                             Used throughout the loop
trns_scr_y              RN      2 ;                             Used outside the loop
trns_X                  RN      3 ;                             Used throughout the loop
trns_X_x0_y             RN      3 ;                             Used outside the loop
trns_Y                  RN      4 ;                             Used throughout the loop
trns_Y_x0_y             RN      4 ;                             Used outside the loop
trns_inc_X_x            RN      5 ;                             Used throughout the loop & outside the loop
trns_inc_Y_x            RN      6 ;                             Used throughout the loop & outside the loop
trns_byte_width         RN      7 ;                             Used throughout the loop
trns_inc_X_y            RN      7 ;                             Used outside the loop
trns_spr_height         RN      8 ; Top 16 bits only.           Used throughout the compiled loop
trns_spr_right          RN      8 ; Bottom 16 bits only.        Used throughout the compiled loop
trns_inc_Y_y            RN      8 ;                             Used outside the loop
trns_out_ptr            RN      9 ;                             Used throughout the loop
trns_line_ptr           RN      9 ;                             Used outside the loop
trns_out_word           RN      10;                             Used throughout the loop
trns_vertex_ptrs        RN      10;                             Used outside the loop
trns_out_mask           RN      11;                             Used throughout the loop
trns_dummy11            RN      11;                              (dummy register - used outside the loop)
trns_out_x              RN      12;                             Used on entry to the compiled loop
trns_workspace_ptr      RN      12;                             Workspace pointer
trns_dummy12            RN      12;                              (dummy register - used everywhere)
trns_in_pixel           RN      14;                             Used in the middle to end of loop
trns_dummy14            RN      14;                              (dummy register - used everywhere)

        GBLA    ldmreg
        GBLA    ldmreg3
        GBLS    ldmreg2

        MACRO
$l      TrnsAsm         $label,$size,$cc
ldmreg  SETA    $size:SHR:2
ldmreg3 SETA    ldmreg+3
ldmreg2 SETS    "$ldmreg3":RIGHT:1
$l
    [ ldmreg>6
        ADR$cc  R4,$label
        LDM$cc.IA R4!,{R4-R9}
        STM$cc.IA R10!,{R4-R9}
        TrnsAsm ($label+6*4),($size-6*4),$cc
    |
      [ ldmreg>1
        ADR$cc.L  R4,$label
Neil Turton's avatar
Neil Turton committed
113
        LDM$cc.IA R4,{R4-R$ldmreg2}
Neil Turton's avatar
Neil Turton committed
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
        STM$cc.IA R10!,{R4-R$ldmreg2}
      |
        LDR$cc  R4,$label
        STR$cc  R4, [R10], #4
      ]
    ]
        MEND


        MACRO
$l      TrnsAsmReg      $reg,$size,$cc
ldmreg  SETA    $size:SHR:2
ldmreg3 SETA    ldmreg+3
ldmreg2 SETS    "$ldmreg3":RIGHT:1
$l      LDM$cc.IA $reg,{R4-R$ldmreg2}
        STM$cc.IA R10!,{R4-R$ldmreg2}
        MEND
Neil Turton's avatar
Neil Turton committed
131 132


Neil Turton's avatar
Neil Turton committed
133 134 135 136 137 138
        MACRO
$l      TrnsBranch      $reg,$op
        SUB     $reg,$reg,R10
        SUB     $reg,$reg,#8
        MOV     $reg,$reg,LSL#6
        MOV     $reg,$reg,LSR#8
Neil Turton's avatar
Neil Turton committed
139
        ORR     $reg,$reg,#$op
Neil Turton's avatar
Neil Turton committed
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
        STR     $reg,[R10],#4
        MEND

        MACRO
$label  DivRem2 $rc, $ra, $rb, $rtemp
$label
        [       debugtr
        TEQ     $rb,#0
        SWIEQ   OS_BreakPt
        ]
        MOV     $rtemp, $rb
        CMP     $rtemp, $ra, LSR #1
01
        MOVLS   $rtemp, $rtemp, LSL #1
        CMPLS   $rtemp, $ra, LSR #1
        BLS     %BT01
        MOV     $rc, #0
02
        CMP     $ra, $rtemp
        SUBCS   $ra, $ra, $rtemp
        ADC     $rc, $rc, $rc
        MOV     $rtemp, $rtemp, LSR #1
        CMP     $rtemp, $rb
        BCS     %BT02
        MEND

Kevin Bracey's avatar
Kevin Bracey committed
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
 [ usemull
        ! 0, "Using SMULL - StrongARM or later only"
 ]

        MACRO
        SSmultD $ra,$rb,$rl,$rh
        ; Asserts to check requirements always meet both options
        ASSERT  $rh = $rl + 1
        ASSERT  $ra <= R8
        ASSERT  $rb <= R8
        ASSERT  $rl <= R7
 [ usemull
    [ $ra = $rl :LOR: $ra = $rh
        ! 0, "Register clash avoided in SSmultD"
        MOV     R14, $ra
        SMULL   $rl,$rh,R14,$rb
    |
        SMULL   $rl,$rh,$ra,$rb
    ]
 |
        BL      arith_SSmultD
        DCB     $ra,$rb,$rl,0
 ]
        MEND


Neil Turton's avatar
Neil Turton committed
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
        MakeSpriteErrorBlock BadFlags,,BadFlgs
        MakeSpriteErrorBlock BadCoordBlock,,BadCBlk
        MakeSpriteErrorBlock BadSourceRectangle,,BadRect
        MakeSpriteErrorBlock BadTransformation,,BadTfrm

badcoordblock
        ADR     R0, ErrorBlock_BadCoordBlock
        addr    r1, Title
        BL      copy_error_one                  ; Always sets the V bit
        B       exitbiggie

nullareasource
        ADR     R0, ErrorBlock_BadSourceRectangle
        addr    r1, Title
        BL      copy_error_one                  ; Always sets the V bit
        B       exitbiggie

badtransformation
        ADR     R0, ErrorBlock_BadTransformation
        addr    r1, Title
        BL      copy_error_one                  ; Always sets the V bit
        B       exitbiggie
Neil Turton's avatar
Neil Turton committed
214

Neil Turton's avatar
Neil Turton committed
215 216 217 218 219 220 221 222
        GBLA    flg_matrix
        GBLA    flg_coordblock
flg_matrix      SETA    1
flg_coordblock  SETA    2

Go_PlotMaskTransformed
        Push    "R1-R9,LR"
; Pretend its a GCOL 8 - use sprite's mask if it has one
Neil Turton's avatar
Neil Turton committed
223
        MOV     R5,#8
Neil Turton's avatar
Neil Turton committed
224 225 226 227 228 229 230 231 232 233 234
; No colour translation
        MOV     R7,#0
        B       %FT01

Go_PutSpriteTransformed
        Push    "R1-R9,LR"
01
        Debug   tr,"Draw sprite: R0,R1,R2 =",R0,R1,R2
        Debug   tr,"Coords, gcol, &scale, &ttr =",R3,R4,R5,R6,R7

        CLRPSR  I_bit, R14              ; re-enable interrupts
Neil Turton's avatar
Neil Turton committed
235

Neil Turton's avatar
Neil Turton committed
236 237
        [       flagbit
        MOV     R14, R5, LSR #4
Neil Turton's avatar
Neil Turton committed
238
        STR     R14, trns_flags2
Neil Turton's avatar
Neil Turton committed
239 240 241 242 243 244 245 246 247 248
        [ widetrans
        BICS    R14, R14, #flg2_ignorettr+flg2_widetrans + flg2_ditheron
        |
        BICS    R14, R14, #flg2_ignorettr + flg2_ditheron
        ]
        ADRNE   R0, ErrorBlock_BadFlags
        addr    r1, Title, NE
        BLNE    copy_error_one          ; Always sets the V bit
        BVS     exitbiggie
        ]
Neil Turton's avatar
Neil Turton committed
249

Neil Turton's avatar
Neil Turton committed
250 251 252 253 254 255 256 257 258 259 260
        AND     R5,R5,#&0F              ; only bottom 4 bits are interesting

        BICS    R14, R3, #flg_matrix:OR:flg_coordblock  ; Check for legal flags
        ADRNE   R0, ErrorBlock_BadFlags
        addr    r1, Title, NE
        BLNE    copy_error_one          ; Always sets the V bit
        BVS     exitbiggie

; see if reason code indicated a sprite name or sprite pointer in R2

        BL      findsprite              ; R2 --> sprite
Neil Turton's avatar
Neil Turton committed
261

Neil Turton's avatar
Neil Turton committed
262 263 264 265 266 267 268 269 270 271 272
        MOVVC   R1,R2                   ; now R1 --> sprite

; read input/output mode variables

        BLVC    readvduvars
        LDRVC   R0,[R1,#spMode]         ; get sprite's original mode
        MOVVC   R14,R0,LSR #27

        STRVC   R14,save_spr_type       ; and derive the sprite type from it
        BLVC    readspritevars
        BVS     exitbiggie
Neil Turton's avatar
Neil Turton committed
273

Neil Turton's avatar
Neil Turton committed
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
        [ ignore_ttr
; check whether it has a palette - if doing <16 to >8 we may use it in preference
; to the translation table

        MOV     R0, #0
        STR     R0, trns_palette

        LDR     R0,[R1,#spImage]
        CMP     R0,#SpriteCBsize
        BEQ     trns_has_no_palette

        LDR     R14,[R1,#spTrans]
        CMP     R14,#SpriteCBsize
        BEQ     trns_has_no_palette

        ;validate it (to exclude 8bpp without full palettes)
        ;test is that palette size should be 8*ncolours
Neil Turton's avatar
Neil Turton committed
291

Neil Turton's avatar
Neil Turton committed
292 293 294 295 296 297 298 299 300
        ;find the lower of the sprite start and mask start
        CMP     R0,R14
        MOVCS   R0,R14
        SUB     R0,R0,#SpriteCBsize

        MOV     R0,R0,LSR #3 ;divide by 8 for number of palette entries
        MOV     R14,#1
        LDR     R9,save_inbpp
        MOV     R14,R14,ASL R9
Neil Turton's avatar
Neil Turton committed
301

Neil Turton's avatar
Neil Turton committed
302 303
        CMP     R14,R0
        BNE     trns_has_no_palette
Neil Turton's avatar
Neil Turton committed
304

Neil Turton's avatar
Neil Turton committed
305
        [       flagbit
Neil Turton's avatar
Neil Turton committed
306 307
        LDR     R14, trns_flags2
        TST     R14, #flg2_ignorettr
Neil Turton's avatar
Neil Turton committed
308
;        BNE     %FT01
Neil Turton's avatar
Neil Turton committed
309
;        [       med01867
Neil Turton's avatar
Neil Turton committed
310 311
;        CMP     R9, #8
;        BNE     trns_has_no_palette ;restrict it to 8bpp full palette only
Neil Turton's avatar
Neil Turton committed
312
;        ]
Neil Turton's avatar
Neil Turton committed
313
        BEQ     trns_has_no_palette
Neil Turton's avatar
Neil Turton committed
314
01
Neil Turton's avatar
Neil Turton committed
315
        |
Neil Turton's avatar
Neil Turton committed
316
;        [       med01867
Neil Turton's avatar
Neil Turton committed
317 318
;        CMP     R9, #8
;        BNE     trns_has_no_palette ;restrict it to 8bpp full palette only
Neil Turton's avatar
Neil Turton committed
319
;        ]
Neil Turton's avatar
Neil Turton committed
320 321 322 323 324 325 326 327
        B       trns_has_no_palette
        ]

        LDR     R14,[R1,#spTrans]
        ADD     R14,R1,#SpriteCBsize
        STR     R14, trns_palette
trns_has_no_palette
       ]
Neil Turton's avatar
Neil Turton committed
328

Neil Turton's avatar
Neil Turton committed
329
; validate supplied translation table (if any)
Neil Turton's avatar
Neil Turton committed
330

331 332
        CMP     R7,R7,ASR #31           ; documented as <=0 being none - now accept 0 or -1
        MOVEQS  R7,#0                   ; 0 ==> no translation
Neil Turton's avatar
Neil Turton committed
333 334
        BLNE    checktrans
        BVS     exitbiggie              ; fault it because it failed
Neil Turton's avatar
Neil Turton committed
335
;
Neil Turton's avatar
Neil Turton committed
336 337 338 339 340 341
        [ ignore_ttr
; if doing a sprite of <16bpp to >8bpp, and it has a palette, change the ttr pointer
; to point at the palette data instead of the ttr data. Note that the two are different
; formats, so there is also a different plotting routine to include too...

        LDR     R14, BPP                               ; output bpp
Neil Turton's avatar
Neil Turton committed
342
        CMP     R14, #16
Neil Turton's avatar
Neil Turton committed
343 344
        MOVCC   R14, #0
        STRCC   R14, trns_palette
Neil Turton's avatar
Neil Turton committed
345
        BCC     %FT45
Neil Turton's avatar
Neil Turton committed
346
        LDR     R14, save_inbpp
Neil Turton's avatar
Neil Turton committed
347
        CMP     R14, #16
Neil Turton's avatar
Neil Turton committed
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
        MOVCS   R14, #0
        STRCS   R14, trns_palette
        BCS     %FT45
        LDR     R14, trns_palette
        TEQ     R14, #0
        MOVNE   R7,R14
        MOVEQ   R14,#0
        STREQ   R14, trns_palette ;only non-zero if going to use this

; trns_palette doubles as a pointer to the palette up this far, and then becomes a
; compilation flag for the macro generation (with the value being passed in as the
; ttr address)

45
        ]
        STR     R7,ColourTTR
        CMP     R7,#0
        BNE     trns_notrans
;
        LDRB    R14,spritecode          ; R14 = bottom 8 bits of reason code
        TEQ     R14,#SpriteReason_PlotMaskTransformed
        LDRNE   R14,save_inbpp
        LDRNE   R0,BPP
        TEQNE   R14,R0                  ; OK if same bpp or mask plotting

        ;however, don't error if going 16>32 or 32>16
        BEQ     trns_notrans ;dispose of the equal case

        CMP     R0,#16
        CMPEQ   R14,#32
        BEQ     trns_notrans

        CMP     R0,#32
        CMPEQ   R14,#16
        BEQ     trns_notrans

        B       errtrans

Neil Turton's avatar
Neil Turton committed
386
trns_notrans
Neil Turton's avatar
Neil Turton committed
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
; adapt mode variables intelligently (account for double pixel modes)

        LDR     R8, Log2bpc
        LDR     R9, Log2bpp
        SUB     R8, R8, R9
        LDR     R0, gwx0
        MOV     R0, R0, ASL R8
        STR     R0, gwx0
        LDR     R0, gwx1
        ADD     R0, R0, #1
        MOV     R0, R0, ASL R8
        STR     R0, gwx1

; Valid registers: R1 - ptr to sprite?, R3 - flags, R4 -> coordinate block, R5 GCOL, R6->matrix/coords, R7->ttr
;        Debug   tr,"Read VDU and sprite:",#gwx0,#gwy0,#gwx1,#gwy1,#orgx,#orgy
;        Debug   tr,"Pointer to sprite:",R1
Neil Turton's avatar
Neil Turton committed
403
; Get coordinate block
Neil Turton's avatar
Neil Turton committed
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425

        LDR     R2, save_inlog2bpp
        TST     R3, #flg_coordblock
        BNE     %FT01

; (whole sprite R0 - left, R8 - top y, R9 - right, R14 - bottom)

        LDR     R14, save_spr_type
        CMP     R14, #0
        LDREQ   R0, [R1, #spLBit]
        MOVEQ   R0, R0, ASR R2
        MOVNE   R0, #0                  ; new format sprites don't have any lh wastage
        LDR     R8, [R1, #spHeight]
        ADD     R8, R8, #1
        LDR     R9, [R1, #spRBit]
        RSB     R9, R9, #31
        LDR     R4, [R1, #spWidth]
        ADD     R4, R4, #1
        RSB     R9, R9, R4, LSL#5
        MOV     R9, R9, ASR R2
        MOV     R14, #0
        B       %FT02
Neil Turton's avatar
Neil Turton committed
426
01
Neil Turton's avatar
Neil Turton committed
427 428 429 430

; Check area passed in

        LDMIA   R4, {R0,R8,R9,R14}
Neil Turton's avatar
Neil Turton committed
431

Neil Turton's avatar
Neil Turton committed
432 433
; If using a matrix then clip source rectangle to sprite

Neil Turton's avatar
Neil Turton committed
434
        TST     R3, #flg_matrix
Neil Turton's avatar
Neil Turton committed
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
        BNE     %FT03
        CMP     R8, #0
        MOVLT   R8, #0
        CMP     R14, #0
        MOVLT   R14, #0
        LDR     R4, [R1, #spHeight]
        ADD     R4, R4, #1
        CMP     R8, R4
        MOVGT   R8, R4
        CMP     R14, R4
        MOVGT   R14, R4
        CMP     R0, #0
        MOVLT   R0, #0
        CMP     R9, #0
        MOVLT   R9, #0

        LDR     R4, [R1, #spLBit]
        ADD     R0, R0, R4, LSR R2
        ADD     R9, R9, R4, LSR R2
        LDR     R4, [R1, #spRBit]
        RSB     R4, R4, #31
        LDR     R10, [R1, #spWidth]
        ADD     R10, R10, #1
        RSB     R4, R4, R10, LSL#5

        CMP     R0, R4, LSR R2
        MOVGT   R0, R4, LSR R2
        CMP     R9, R4, LSR R2
        MOVGT   R9, R4, LSR R2
        CMP     R0, R9
        CMPNE   R8, R14
        BEQ     nullareasource
        B       %FT02
03

; If not using a matrix then check valid source area

        CMP     R0, R9
        CMPNE   R8, R14
        BEQ     nullareasource
        CMP     R8, #0
        CMPGE   R14, #0
        BLT     badcoordblock
        LDR     R4, [R1, #spHeight]
        ADD     R4, R4, #1
        CMP     R8, R4
        CMPLE   R14, R4
        BGT     badcoordblock
        CMP     R0, #0
        CMPGE   R9, #0
        BLT     badcoordblock

        LDR     R4, [R1, #spLBit]
        ADD     R0, R0, R4, LSR R2
        ADD     R9, R9, R4, LSR R2
        LDR     R4, [R1, #spRBit]
        RSB     R4, R4, #31
        LDR     R10, [R1, #spWidth]
        ADD     R10, R10, #1
        RSB     R4, R4, R10, LSL#5

        CMP     R0, R4, LSR R2
        CMPLE   R9, R4, LSR R2
        BGT     badcoordblock
02
        TST     R3, #flg_matrix
        BNE     coords_passed_in

; Valid registers: R0,R8,R9,R14 - source rect, R1 - ptr to sprite, R5 GCOL, R6->matrix/coords, R7->ttr
; Set up input path for draw - move to R0,R8, move to R9,R14, end path

        Push    "R0,R1,R2,R3,R4,R5,R7,R8,R9,R10,R11,R12,R14"
        SUB     sp, sp, #64
        Push    "R12"
        LDR     R11, inlog2px
        ADD     R11, R11, #8
        MOV     R0, R0, ASL R11
        MOV     R9, R9, ASL R11
        LDR     R11, inlog2py
        ADD     R11, R11, #8
        MOV     R8, R8, ASL R11
        MOV     R14, R14, ASL R11
        ADD     R12, SP, #4
        MOV     R10, R12
        MOV     R11, #2
        STMIA   R10!, {R11}
        STMIA   R10!, {R0,R8,R11}
        STMIA   R10!, {R9}
        STMIA   R10!, {R8,R11}
        MOV     R11, #0
        STMIA   R10!, {R0,R14}
        STMIA   R10!, {R11}

; Transform the path

        MOV     R0, R12
        MOV     R1, #0
Neil Turton's avatar
Neil Turton committed
532
        MOV     R2, R6
Neil Turton's avatar
Neil Turton committed
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
        MOV     R3, #0
        SWI     Draw_TransformPath
        ADDVS   sp, sp, #64+8
        Pull    "R1,R2,R3,R4,R5,R7,R8,R9,R10,R11,R12,R14",VS
        BVS     exitbiggie

; Recover R6

        ADD     R10, R12, #4
        LDMIA   R10!, {R0,R3,R4,R6,R8,R9,R11,R14}
        Pull    "R12"
        ADR     R10, save_outoffset
        STMIA   R10!, {R0,R3,R6,R8}
        ADD     R6, R6, R11
        ADD     R8, R8, R14
        SUB     R6, R6, R0
        SUB     R8, R8, R3
        STMIA   R10!,{R6,R8,R11,R14}
        ADR     R6, save_outoffset
        ADD     sp, sp, #64
        Pull    "R0,R1,R2,R3,R4,R5,R7,R8,R9,R10,R11,R12,R14"

; Make Y values offset from the top of the sprite, not the bottom

coords_passed_in
        LDR     R2, [R1, #spHeight]
        ADD     R2, R2, #1
        SUB     R8, R2, R8
Neil Turton's avatar
Neil Turton committed
561
        SUB     R14, R2, R14
Neil Turton's avatar
Neil Turton committed
562 563 564 565 566 567 568 569 570 571 572 573 574 575

; Get R4 = distance from top of sprite, R2 = height of sprite, and set R8,R14 to be offset from R4

        SUBS    R2, R8, R14
        RSBMI   R2, R2, #0
        MOVMI   R4, R8
        MOVPL   R4, R14
        SUB     R8, R8, R4
        SUB     R14, R14, R4

; Store height, left, right of sprite for inner loop

        SUB     sp, sp, #trns_spr_vars_end
        CMP     R9, R0
Neil Turton's avatar
Neil Turton committed
576
        ORRGT   R10, R9, R2, LSL#16
Neil Turton's avatar
Neil Turton committed
577 578 579 580 581 582 583 584 585 586 587 588
        ORRLE   R10, R0, R2, LSL#16
        STR     R10, trns_comp_spr_height  ;       Height in top 16 bits, right side in bottom 16 bits
        STRGT   R0, trns_comp_spr_left    ;       Left side in bottom 16 bits (measurements in pixels)
        STRLE   R9, trns_comp_spr_left    ;       Left side in bottom 16 bits (measurements in pixels)

; Add R4*sprite_byte_width to sprite_pixel_data_start to give top of sprite, and store for loop

        LDR     R2,[r1,#spMode]
        Debug   ag,"spMode is",R2

        LDR     R2, [R1, #spImage]
        LDR     R10, [R1, #spWidth]
Neil Turton's avatar
Neil Turton committed
589
        Debug   ag,"spWidth is",R10
Neil Turton's avatar
Neil Turton committed
590 591
        Debug   ag,"sprite is at",R1
        ADD     R10, R10, #1
Neil Turton's avatar
Neil Turton committed
592
        LSL     R10, 2
Neil Turton's avatar
Neil Turton committed
593 594
        MLA     R11, R10, R4, R2
        ADD     R11, R11, R1
Neil Turton's avatar
Neil Turton committed
595 596
        STR     R11, trns_comp_spr_start

Neil Turton's avatar
Neil Turton committed
597
; and we have to do the same for the mask data now
Neil Turton's avatar
Neil Turton committed
598 599
; for now we just save the R4 value and deal with it once we have the mask
; equivalent of spWidth computed for the mask
Neil Turton's avatar
Neil Turton committed
600 601 602 603

        STR     R4, trns_comp_mask_base

; Work out byte width << 3-input_bpp, and store for loop
Neil Turton's avatar
Neil Turton committed
604 605

        LDR     R4, save_inlog2bpp
Neil Turton's avatar
Neil Turton committed
606
        CMP     R4, #4
Neil Turton's avatar
Neil Turton committed
607 608 609
        BCC     %FT89

        SUB     R4, R4, #3
Neil Turton's avatar
Neil Turton committed
610 611 612
        MOV     R11, R10, LSL #3
        MOV     R10, R10, LSR R4
        B       %FT88
Neil Turton's avatar
Neil Turton committed
613
89
Neil Turton's avatar
Neil Turton committed
614 615 616
        RSB     R4, R4, #3
        MOV     R11, R10, LSL #3
        MOV     R10, R10, LSL R4
Neil Turton's avatar
Neil Turton committed
617
88
Neil Turton's avatar
Neil Turton committed
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638

        STR     R10, trns_comp_spr_byte_width

        ANDS    R11, R10, #&1F
        MOVNE   R11, #32
        ADD     R11, R11, R10
        BIC     R11, R11, #&1F

        STR     R11, trns_comp_spr_mask_width   ; used only for 1bpp masks

        ;the mask_base was used earlier for the number of rows to go into the
        ;data, so now we turn that into a byte offset

        LDR     R10, trns_comp_mask_base        ; recover row number
        MUL     R10, R11, R10                   ; convert to offset (bits)
        MOV     R10, R10, LSR #3                ; convert to bytes
        STR     R10, trns_comp_mask_base

; Get mask offset and store ttr pointer (clear mask GCOL bit if there is no mask)

        STR     R7, trns_comp_spr_ttr
Robert Sprowson's avatar
Robert Sprowson committed
639

Neil Turton's avatar
Neil Turton committed
640 641 642
        LDR     R10, BPP
        SUB     R10, R10,#1
        MOV     R11, #1:SHL:31
Neil Turton's avatar
Neil Turton committed
643 644
        MOV     R11, R11, ASR R10
        STR     R11, trns_masking_word                  ; suitable mask for pixels
Neil Turton's avatar
Neil Turton committed
645 646 647
        Debug   tr,"trns_masking_word",R11

        LDR     R10, [R1, #spTrans]
Neil Turton's avatar
Neil Turton committed
648
        LDR     R11, [R1, #spImage]
Neil Turton's avatar
Neil Turton committed
649 650 651 652 653 654 655 656 657

        Debug   ag,"trans and image offsets",R10,R11

        SUBS    R11, R10, R11
        BICEQ   R5, R5, #8                 ; no mask, so can't do a plot with b3 set

        Debug   ag,"trans minus image",R11

        LDR     R4, save_inlog2bpp
Neil Turton's avatar
Neil Turton committed
658
        CMP     R4, #4
Neil Turton's avatar
Neil Turton committed
659 660 661
        RSBCC   R4, R4, #3
        SUBCS   R4, R4, #3
        MOVCC   R11, R11, LSL R4
Neil Turton's avatar
Neil Turton committed
662
        MOVCS   R11, R11, LSR R4
Neil Turton's avatar
Neil Turton committed
663 664

        ; R4 is finished with now, so used as a working register for the mask stuff
Neil Turton's avatar
Neil Turton committed
665

Neil Turton's avatar
Neil Turton committed
666 667 668 669 670 671
        LDR     R10,[R1,#spTrans]             ; re-fetch offset to mask
        ADD     R10,R10,R1                    ; turn into absolute address
        LDR     R4, trns_comp_mask_base       ; fetch byte offset within 1bpp mask data
        ADD     R10,R10,R4                    ; include it
        STR     R10,trns_comp_mask_base       ; and store back the final result
        Debug   ag,"mask_base is",R10
Neil Turton's avatar
Neil Turton committed
672 673

        STR     R11, trns_comp_spr_masko
Neil Turton's avatar
Neil Turton committed
674 675 676 677 678
        Debug   ag,"stored masko as",R11

        Debug   tr,"Coordinate block:",R0,R8,R9,R14
        Debug   tr,"Mask offset:",#trns_comp_spr_masko
        Debug   tr,"Flags, GCOL, &Screen block, &TTR",R3, R5, R6, R7
Neil Turton's avatar
Neil Turton committed
679 680
        Debug   tr,"Height/right, left, spr_start, spr_byte_width",#trns_comp_spr_height,#trns_comp_spr_left,#trns_comp_spr_start,#trns_comp_spr_byte_width

Neil Turton's avatar
Neil Turton committed
681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706
; Copy the coordinate block
; Valid registers: R0,R8,R9,R14 - source rect, R1 - ptr to sprite, R5 GCOL, R6->matrix/coords, R7->ttr
; copy coordinates, adding graphics origin

        Push    "R1,R5,R7,R12"
        Push    "R0,R8,R9,R14"
        ADR     R0, trns_spr_xcoords + 4*8

; get O.S. to pixel shift (account for double pixel modes)

        LDR     R1, log2px
        LDR     R2, Log2bpp
        ADD     R1, R1, R2
        LDR     R2, Log2bpc
        SUB     R1, R1, R2
        LDR     R2, log2py

; get graphics origin

        LDR     R3, orgx
        LDR     R4, orgy

; get coordinates

        LDMIA   R6, {R5,R6,R7,R8,R9,R10,R11,R12}

Neil Turton's avatar
Neil Turton committed
707
; x coords
Neil Turton's avatar
Neil Turton committed
708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747

        ADD     R14, R7, R11
        SUB     R14, R14, R5
        CMP     R14, R9
        Pull    "R0,R8,R9,R14",NE
        Pull    "R1,R5,R7,R12",NE
        ADDNE   sp, sp, #trns_spr_vars_end
        BNE     badtransformation
        ADD     R5, R5, R3, LSL#8
        ADD     R7, R7, R3, LSL#8
        ADD     R9, R9, R3, LSL#8
        ADD     R11, R11, R3, LSL#8
        MOV     R5, R5, ASR R1
        MOV     R7, R7, ASR R1
        MOV     R9, R9, ASR R1
        MOV     R11, R11, ASR R1
        STMIA   R0!, {R5,R7,R9,R11}

; y coordinates

        ADD     R14, R8, R12
        SUB     R14, R14, R6
        CMPNE   R14, R10
        Pull    "R0,R8,R9,R14",NE
        Pull    "R1,R5,R7,R12",NE
        ADDNE   sp, sp, #trns_spr_vars_end
        BNE     badtransformation
        ADD     R6, R6, R4, LSL#8
        ADD     R8, R8, R4, LSL#8
        ADD     R10, R10, R4, LSL#8
        ADD     R12, R12, R4, LSL#8
        MOV     R6, R6, ASR R2
        MOV     R8, R8, ASR R2
        MOV     R10, R10, ASR R2
        MOV     R12, R12, ASR R2
        STMIA   R0!, {R6,R8,R10,R12}

        Debug tr,"Transformed coords are:",R5,R6,R7,R8
        Debug tr,"Transformed coords are:",R9,R10,R11,R12

Neil Turton's avatar
Neil Turton committed
748
; Get determinant
Neil Turton's avatar
Neil Turton committed
749 750 751 752 753 754 755 756

        SUB     R9, R7, R5      ; x1
        SUB     R10, R11, R5     ; x2
        SUB     R11, R8, R6      ; y1
        SUB     R12, R12, R6     ; y2

        Debug tr,"x1,x2,y1,y2",R9,R10,R11,R12

Neil Turton's avatar
Neil Turton committed
757
; R4,5 = x1 * y2
Neil Turton's avatar
Neil Turton committed
758 759

        MOV     R0, R9
Neil Turton's avatar
Neil Turton committed
760
        MOV     R1, R12
Kevin Bracey's avatar
Kevin Bracey committed
761
        SSmultD R0,R1,R4,R5
Neil Turton's avatar
Neil Turton committed
762

Neil Turton's avatar
Neil Turton committed
763
; R6,7 = x2 * y1
Neil Turton's avatar
Neil Turton committed
764 765 766

        MOV     R0, R10
        MOV     R1, R11
Kevin Bracey's avatar
Kevin Bracey committed
767
        SSmultD R0,R1,R6,R7
Neil Turton's avatar
Neil Turton committed
768 769 770 771

; R4,R5 = x1*y2 - x2*y1 (48.16 precision)

        SUBS    R4, R4, R6
Neil Turton's avatar
Neil Turton committed
772
        SBC     R5, R5, R7
Neil Turton's avatar
Neil Turton committed
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793

        Debug tr,"R4,R5,R6,R7:",R4,R5,R6,R7
; R4,R5 = x1*y2 - x2*y1 / 4 (48.14 precision)

        MOV     R4, R4, LSR#2
        ORR     R4, R4, R5,LSL#30
        MOV     R5, R5, ASR#2

; R6,R7 = 1 / (x1*y2 - x2*y1) (16.48 precision)

        TEQ     R4, #0
        TEQEQ   R5, #0
        MOVEQ   R6, #0
        MOVEQ   R7, #0
        BEQ     trns_division_by_zero
        MOV     R0, #0
        MOV     R1, #&40000000
        Debug tr,"Dividing:",R0,R1,R4,R5
        mextralong_divide R6,R7,R0,R1,R4,R5,R2,R3,R8
        Debug tr,"Gives:",R6,R7

Neil Turton's avatar
Neil Turton committed
794
trns_division_by_zero
Neil Turton's avatar
Neil Turton committed
795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826
        LDMFD   sp, {R0,R1,R2,R3}
        SUBS    R2, R2, R0
;        RSBMI   R2, R2, #0
        SUBS    R3, R3, R1
;        RSBMI   R3, R3, #0

; spr_inc_X_x = det*y2 [ * xsize ]

        MOV     R0, R12
        MOV     R1, R2
        BL      produce_increment
        MOV     R12, R4

; spr_inc_Y_x = det*-y1 [ * ysize ]

        RSB     R0, R11, #0
        MOV     R1, R3
        BL      produce_increment
        MOV     R11, R4

; spr_inc_X_y = det*-x2 [ * xsize ]

        RSB     R0, R10, #0
        MOV     R1, R2
        BL      produce_increment
        MOV     R10, R4

; spr_inc_Y_y = det*x1 [ * ysize ]

        MOV     R0, R9
        MOV     R1, R3
        BL      produce_increment
Neil Turton's avatar
Neil Turton committed
827
        MOV     R9, R4
Neil Turton's avatar
Neil Turton committed
828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888

; Store increments

        STR     R12, trns_spr_inc_X_x + 8*4
        STR     R11, trns_spr_inc_Y_x + 8*4
        STR     R10, trns_spr_inc_X_y + 8*4
        STR     R9, trns_spr_inc_Y_y + 8*4
        Pull    "R0,R8,R9,R14"
        Pull    "R1,R5,R7,R12"
        Debug   tr,"Coordinate block:",R0,R8,R9,R14

; thats all the horrid fixed point stuff out of the way
; Find the top y coordinate

        ADR     R3, trns_spr_ycoords
        LDMIA   R3!, {R4,R6,R10,R11}
        CMP     R6, R4
        MOVGT   R4, R6
        CMP     R10, R4
        MOVGT   R4, R10
        CMP     R11, R4
        MOVGT   R4, R11
        MOV     R2, R8

; Valid registers: R5 GCOL, R7->ttr, R4 - maximum ycoordinate of area
;                                       Get top y coordinate of centre of line being drawn in R1

        SUB     R1, R4, #128
        MOV     R1, R1, ASR#8
        LDR     R3, gwy1
        CMP     R1, R3
        MOVGT   R1, R3
        STR     R1, save_ycoord
        Debug tr,"Top coordinate on screen (PIXELS) is:",R1

;                                       Get address of line on screen

        LDR     R3, ywindlimit
        SUB     R3, R3, R1
        LDR     R8, screenstart
        LDR     R6, linelength
        MLA     R6, R3, R6, R8
        STR     R6, trns_spr_lineptr
;                                       Get ECF pointer
        MOV     R6, #VduDriverWorkSpace + BgEcfOraEor
        AND     R3, R3, #7
        ADD     R6, R6, R3,LSL#3
;        Debug   tr, "Ecf pointer is:",R6
        STR     R6, trns_ecf_ptr

;spr_X_x0_y% += ((screen_y%-y(0)) * (!asm_spr_inc_X_y)) / 256
; screen_y%-y(0) = R6.R4

        MOV     R1, R1, ASL#8
        ADD     R1, R1, #128
        LDR     R4, trns_spr_ycoords
        SUB     R4, R1, R4
;        Debug tr,"scry%-y0:",R4
        MOV     R6, R4, ASR#16
        BIC     R4, R4, R6, LSL#16

Neil Turton's avatar
Neil Turton committed
889
; inc_X_y = R8.R9
Neil Turton's avatar
Neil Turton committed
890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906

        LDR     R14, trns_spr_inc_X_x
;        Debug tr,"IncXx",R14
        LDR     R14, trns_spr_inc_X_y
;        Debug tr,"incXy,Xx0",R14,R0
        MOV     R8, R14, ASR#16
        BIC     R9, R14, R8, LSL#16

; multiply

        MUL     R10, R9, R6
        MLA     R10, R8, R4, R10
        MUL     R11, R6, R8
        MUL     R14, R9, R4
        MOV     R14, R14, LSR#8
        ADD     R10, R14, R10,LSL #8
        ADD     R0, R10, R0,LSL #16
Neil Turton's avatar
Neil Turton committed
907
        ADD     R0, R0, R11,LSL#24
Neil Turton's avatar
Neil Turton committed
908 909 910

        Debug tr,"Xx0y:",R0
;spr_Y_x0_y% += ((screen_y%-y(0)) * (!asm_spr_inc_Y_y)) / 256
Neil Turton's avatar
Neil Turton committed
911
; inc_Y_y = R8.R9
Neil Turton's avatar
Neil Turton committed
912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928

        LDR     R14, trns_spr_inc_Y_y
        Debug tr,"incYy=",R14
        MOV     R8, R14, ASR#16
        BIC     R9, R14, R8, LSL#16
        MUL     R10, R9, R6
        MLA     R10, R8, R4, R10
        MUL     R11, R6, R8
        MUL     R14, R9, R4
        MOV     R14, R14, LSR#8
        ADD     R10, R14, R10,LSL #8
        ADD     R2, R10, R2,LSL#16
        ADD     R2, R2, R11,LSL#24

; Valid registers: R0,R2 - X_x0_y/Y_x0_y, R5 GCOL, R7->ttr

        STR     R0, trns_spr_X_x0_y
Neil Turton's avatar
Neil Turton committed
929
        STR     R2, trns_spr_Y_x0_y
Neil Turton's avatar
Neil Turton committed
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 968 969 970 971
        Debug tr,"Top corner (w.r.t. sprite) is:",R0,R2

; Now compile the code

        BL      compile_transform_code
        ADR     R10, codebuffer
        STR     R10, trns_codebuffer
        Debug tr,"Code compiled:",R10

; Now, set up the edges in the edge block

        ADR     R0, trns_spr_edgeblock
        MOV     R1, #0
        ADR     R2, trns_spr_xcoords
        LDMIA   R2, {R2,R3,R4,R5, R6,R7,R8,R9}

; Edge 0->1

        CMP     R6, R7
        STMGTIA R0!,{R1,R3,R7}
        STMGTIA R0!,{R2,R6}
        STMLEIA R0!,{R1,R2,R6}
        STMLEIA R0!,{R3,R7}

; Edge 1->2

        ADD     R0, R0, #8
        CMP     R7, R8
        STMGTIA R0!,{R1,R4,R8}
        STMGTIA R0!,{R3,R7}
        STMLEIA R0!,{R1,R3,R7}
        STMLEIA R0!,{R4,R8}

; Edge 0->3

        ADD     R0, R0, #8
        CMP     R6, R9
        STMGTIA R0!,{R1,R5,R9}
        STMGTIA R0!,{R2,R6}
        STMLEIA R0!,{R1,R2,R6}
        STMLEIA R0!,{R5,R9}

Neil Turton's avatar
Neil Turton committed
972
; Edge 3->2
Neil Turton's avatar
Neil Turton committed
973 974 975 976 977 978

        ADD     R0, R0, #8
        CMP     R9, R8
        STMGTIA R0!,{R1,R4,R8}
        STMGTIA R0!,{R5,R9}
        STMLEIA R0!,{R1,R5,R9}
Neil Turton's avatar
Neil Turton committed
979
        STMLEIA R0!,{R4,R8}
Neil Turton's avatar
Neil Turton committed
980 981 982 983 984 985 986 987 988 989 990
        ADD     R0, R0, #8
        MVN     R1, #0
        STR     R1, [R0]

;;        Debug tr,"Active edge list:",#trns_spr_edgeblock,#trns_spr_edgeblock+4,#trns_spr_edgeblock+8,#trns_spr_edgeblock+12,#trns_spr_edgeblock+16,#trns_spr_edgeblock+20,#trns_spr_edgeblock+24
;;        Debug tr,"Active edge list:",#trns_spr_edgeblock+28,#trns_spr_edgeblock+32,#trns_spr_edgeblock+36,#trns_spr_edgeblock+40,#trns_spr_edgeblock+44,#trns_spr_edgeblock+48,#trns_spr_edgeblock+52
;;        Debug tr,"Active edge list:",#trns_spr_edgeblock+56,#trns_spr_edgeblock+60,#trns_spr_edgeblock+64,#trns_spr_edgeblock+68,#trns_spr_edgeblock+72,#trns_spr_edgeblock+76,#trns_spr_edgeblock+80
;;        Debug tr,"Active edge list:",#trns_spr_edgeblock+84,#trns_spr_edgeblock+88,#trns_spr_edgeblock+92,#trns_spr_edgeblock+96,#trns_spr_edgeblock+100,#trns_spr_edgeblock+104,#trns_spr_edgeblock+108

; Get top Y coordinate

Neil Turton's avatar
Neil Turton committed
991
        LDR     R1, save_ycoord
Neil Turton's avatar
Neil Turton committed
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
        MOV     R11, #3

; Start loop - looping until all edges are deactivated or below Y coord

00
        LDR     R14, gwy0
        CMP     R1, R14
        BLT     trns_completed_drawing

; Activate any new edges, deactivate old ones (R11 = count of deactivated edges)

        ADR     R10, trns_spr_edgeblock
01
        LDMIA   R10, {R0,R5,R6,R7,R8,R9,R14}

; Checked all the edges?

        CMN     R0, #1
Neil Turton's avatar
Neil Turton committed
1010
        BEQ     activated_all_edges
Neil Turton's avatar
Neil Turton committed
1011 1012 1013 1014 1015 1016 1017 1018 1019

; If dead then ignore

        TST     R0, #trns_deactivated
        BNE     edge_inactive

; If active then shoule we deactivate it?

        TST     R0, #trns_activated
Neil Turton's avatar
Neil Turton committed
1020
        BNE     edge_active
Neil Turton's avatar
Neil Turton committed
1021

Neil Turton's avatar
Neil Turton committed
1022
; Test for activation
Neil Turton's avatar
Neil Turton committed
1023 1024 1025

        SUB     R14, R8, #128
        CMP     R1, R14, ASR #8
Neil Turton's avatar
Neil Turton committed
1026
        BGT     edge_inactive
Neil Turton's avatar
Neil Turton committed
1027

Neil Turton's avatar
Neil Turton committed
1028
; Activate an edge
Neil Turton's avatar
Neil Turton committed
1029

Neil Turton's avatar
Neil Turton committed
1030
        SUB     R8, R8, #128
Neil Turton's avatar
Neil Turton committed
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 1059 1060 1061 1062 1063 1064 1065 1066 1067
        SUB     R6, R6, #128
        ORR     R0, R0, #trns_activated

; Calculate R3=ABS(deltaX) and R4=ABS(deltaY).

        SUBS    R3,R7,R5
        RSBLT   R3,R3,#0
        SUB     R4,R8,R6                ;Must be correct sign already - lines are sorted wrt Y coords.

; Record direction of line as 1 or -1 in top two bits of flags

        ORR     R0,R0,#&40000000        ;line goes rightwards
        ORRGE   R0,R0,#&80000000        ;Processor Status preserved from above - GE if line goes leftwards

; Now calculate target Y co-ordinate - the line must stop after this Y value is reached.

        MOV     R2,R6,ASR #8
        ADD     R2,R2,#1
        CMP     R1, R2
        MOVLT   R0, #trns_deactivated
        BLT     edge_inactive

; Valid registers: R0-flags, R1-current Y, R2-target Y, R3,R4-dX,dY,
;                  R7,R8-Upper x,y, R10-store for edge, R11-count of deactivated edges
; Now get Bresenham error in R6.

        AND     R14,R7,#&FF
        MOV     R7,R7,ASR #8
        ADD     R6,R3,R4                ;ABS(deltaX)+ABS(deltaY)
        CMP     R6,#&80000000:SHR:8
        BLO     out_qfill_spbres

; Only do complicated stuff if simple stuff will overflow

out_qfill_dpbres
        Push    "R0,R4,R5,R7"

Neil Turton's avatar
Neil Turton committed
1068
; R7=-1,C=1 for leftward lines, R7=0,C=0 for rightward lines.
Neil Turton's avatar
Neil Turton committed
1069 1070 1071 1072 1073 1074 1075 1076 1077 1078

        MOVS    R7,R0,ASR #32

; Get R0=real sub-X coordinate on screen (R14=subpixel now)

        SUB     R0,R14,#128
        RSBCS   R0,R0,#0

; R4,R5 = R0*dY , R6,R7=R4,R5 -1 if leftward,+0 i rightward

Kevin Bracey's avatar
Kevin Bracey committed
1079
        SSmultD R0,R4,R4,R5             ;subpixelX * ABS(deltaY) into R4,R5
Neil Turton's avatar
Neil Turton committed
1080 1081 1082 1083 1084 1085
        ADDS    R6,R4,R7                ;Accumulate into R6,R7
        ADC     R7,R5,R7

; R6,R7 += R0*dX

        AND     R0,R8,#255
Kevin Bracey's avatar
Kevin Bracey committed
1086
        SSmultD R0,R3,R4,R5
Neil Turton's avatar
Neil Turton committed
1087 1088 1089 1090 1091 1092 1093 1094
        ADDS    R6,R4,R6
        ADC     R7,R5,R7

; Change error to full pixel instead of 256ths pixels

        MOV     R6,R6,LSR #8
        ORR     R6,R6,R7,LSL #24
        Pull    "R0,R4,R5,R7"
Neil Turton's avatar
Neil Turton committed
1095
        B       out_qfill_bresdone
Neil Turton's avatar
Neil Turton committed
1096 1097 1098 1099 1100

; Do simple stuff

out_qfill_spbres

Neil Turton's avatar
Neil Turton committed
1101
; R6=-1,C=1 for leftward lines, R6=0,C=0 for rightward lines.
Neil Turton's avatar
Neil Turton committed
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122

        MOVS    R6,R0,ASR #32

; Get R0=real sub-X coordinate on screen (R14=subpixel now)

        SUB     R14,R14,#128
        RSBCS   R14,R14,#0
        MLA     R6,R14,R4,R6            ;Accumulate subpixelX * ABS(deltaY)
        AND     R14,R8,#255
        MLA     R6,R14,R3,R6            ;Accumulate subpixelY * ABS(deltaX)
        MOV     R6,R6,ASR #8            ;Change units to full pixels

; Now R6=Bresenham value

out_qfill_bresdone
        MOV     R8,R8,ASR #8

; Now advance the edge until we're on the right scan line and the Bresenham
; value is negative.

        CMP     R1,R2                   ;Don't bother if we're below target Y
1123 1124 1125 1126
        BLT     out_qfill_doneclip
        SUBS    R8,R8,R1                ;Must set GT or EQ
        BLGT    out_qfill_fastclip
        CMP     R6,#0                   ;So this can only happen if R1 >= R2
Neil Turton's avatar
Neil Turton committed
1127 1128 1129 1130
out_qfill_Xcliploop
        ADDGE   R7,R7,R0,ASR #30        ;Advance in X direction as far as
        SUBGES  R6,R6,R4                ;  possible
        BGE     out_qfill_Xcliploop
1131
out_qfill_doneclip
Neil Turton's avatar
Neil Turton committed
1132 1133 1134 1135 1136 1137 1138
        ADD     R6,R6,R3

; Store flags,targetY,deltaX,deltaY

        STMIA   R10!,{R0,R2,R3,R4}
        STMIA   R10!, {R6,R7,R8}
        B       edge_no_store
Neil Turton's avatar
Neil Turton committed
1139
edge_active
Neil Turton's avatar
Neil Turton committed
1140 1141 1142 1143 1144 1145 1146

; If now below it then kill it

        CMP     R1, R5                  ; Check for deactivating the edge
        MOVLT   R0, #trns_deactivated
        SUBLT   R11, R11, #1
        ADD     R8,R8,R6                ;Adjust Bresenham value for Y move
Neil Turton's avatar
Neil Turton committed
1147
edge_inactive
Neil Turton's avatar
Neil Turton committed
1148 1149 1150
        STMIA   R10!, {R0,R5,R6,R7,R8,R9,R14}
edge_no_store
        B       %BT01
Neil Turton's avatar
Neil Turton committed
1151
activated_all_edges
Neil Turton's avatar
Neil Turton committed
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
        CMP     R11, #0
        BLT     trns_completed_drawing

;;        Debug tr,"Active edge list:",#trns_spr_edgeblock,#trns_spr_edgeblock+4,#trns_spr_edgeblock+8,#trns_spr_edgeblock+12,#trns_spr_edgeblock+16,#trns_spr_edgeblock+20,#trns_spr_edgeblock+24
;;        Debug tr,"Active edge list:",#trns_spr_edgeblock+28,#trns_spr_edgeblock+32,#trns_spr_edgeblock+36,#trns_spr_edgeblock+40,#trns_spr_edgeblock+44,#trns_spr_edgeblock+48,#trns_spr_edgeblock+52
;;        Debug tr,"Active edge list:",#trns_spr_edgeblock+56,#trns_spr_edgeblock+60,#trns_spr_edgeblock+64,#trns_spr_edgeblock+68,#trns_spr_edgeblock+72,#trns_spr_edgeblock+76,#trns_spr_edgeblock+80
;;        Debug tr,"Active edge list:",#trns_spr_edgeblock+84,#trns_spr_edgeblock+88,#trns_spr_edgeblock+92,#trns_spr_edgeblock+96,#trns_spr_edgeblock+100,#trns_spr_edgeblock+104,#trns_spr_edgeblock+108
;;        Debug tr,"Number of active/not yet activated edges:",R11

; Move on all active lines
Neil Turton's avatar
Neil Turton committed
1162

Neil Turton's avatar
Neil Turton committed
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176
        ADR     R10, trns_spr_edgeblock
01
        LDMIA   R10!, {R0,R2,R3,R4,R6,R7,R8}
        CMN     R0, #1
        BEQ     trns_draw_line
        TST     R0, #trns_activated
        BEQ     %BT01

; R0-flags, R2 - target Y, R3 - deltaX, R4-deltaY
; R6-Bresenham error value, R7-current X

        SUB     R8,R7,R0,ASR #31        ;Calculate crossing X
        CMP     R1,R2                   ;Stop if already below target
        BLT     trns_deactivate_2
1177
;        CMP     R4,R6,ASR #3            ;Use fast code?
Neil Turton's avatar
Neil Turton committed
1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206
;        BLLE    out_qfill_fasthoriz
        CMP     R6,#0                   ;Are we still below the edge?
02
        ADDGE   R7,R7,R0,ASR #30        ;Make X moves until we're above the
        SUBGES  R6,R6,R4                ;  edge, adjusting Bresenham value
        BGE     %BT02                   ;  for them
        STMDB   R10, {R0,R2,R3,R4,R6,R7,R8}
        B       %BT01

trns_deactivate_2
        MOV     R0, #trns_deactivated
        STMDB   R10, {R0,R2,R3,R4,R6,R7,R8}
        B       %BT01

; Now find the pair of lines which are active

trns_draw_line
;;        Debug tr,"Active edge list:",#trns_spr_edgeblock,#trns_spr_edgeblock+4,#trns_spr_edgeblock+8,#trns_spr_edgeblock+12,#trns_spr_edgeblock+16,#trns_spr_edgeblock+20,#trns_spr_edgeblock+24
;;        Debug tr,"Active edge list:",#trns_spr_edgeblock+28,#trns_spr_edgeblock+32,#trns_spr_edgeblock+36,#trns_spr_edgeblock+40,#trns_spr_edgeblock+44,#trns_spr_edgeblock+48,#trns_spr_edgeblock+52
;;        Debug tr,"Active edge list:",#trns_spr_edgeblock+56,#trns_spr_edgeblock+60,#trns_spr_edgeblock+64,#trns_spr_edgeblock+68,#trns_spr_edgeblock+72,#trns_spr_edgeblock+76,#trns_spr_edgeblock+80
;;        Debug tr,"Active edge list:",#trns_spr_edgeblock+84,#trns_spr_edgeblock+88,#trns_spr_edgeblock+92,#trns_spr_edgeblock+96,#trns_spr_edgeblock+100,#trns_spr_edgeblock+104,#trns_spr_edgeblock+108
;;        Debug tr,"Number of active/not yet activated edges:",R11
        ADR     R10, trns_spr_edgeblock
01
        LDMIA   R10!, {R0,R2,R3,R4,R5,R6,R7}
        CMN     R0, #1
        BEQ     trns_completed_drawing
        TST     R0, #1
        BEQ     %BT01
Neil Turton's avatar
Neil Turton committed
1207
01
Neil Turton's avatar
Neil Turton committed
1208 1209 1210 1211
        LDMIA   R10!, {R0,R2,R3,R4,R5,R6,R8}
        CMN     R0, #1
        BEQ     trns_completed_drawing
        TST     R0, #1
Neil Turton's avatar
Neil Turton committed
1212
        BEQ     %BT01
Neil Turton's avatar
Neil Turton committed
1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310

; R6,R7 are x coords to plot between at current Y

        Push    "R1,R11,R12"
        MOV     trns_scr_y, R1
        MOV     trns_scr_lx, R7
        MOV     trns_scr_rx, R8
        ASSERT trns_scr_lx<>R6
        ASSERT trns_scr_y<>R6
        ASSERT trns_scr_y<>R7
        LDR     R14, trns_ecf_ptr + 3*4
        LDMIA   R14!, {trns_X_x0_y, trns_Y_x0_y}
        STR     trns_X_x0_y, trns_comp_ecf_ora + 3*4
        STR     trns_Y_x0_y, trns_comp_ecf_eor + 3*4
        CMP     R14, #VduDriverWorkSpace + BgEcfOraEor+64
        MOVGE   R14, #VduDriverWorkSpace + BgEcfOraEor
        STR     R14, trns_ecf_ptr + 3*4
        ADR     R14, trns_spr_X_x0_y + 3*4
        LDMIA   R14, {trns_X_x0_y,trns_Y_x0_y,trns_inc_X_x,trns_inc_Y_x,trns_inc_X_y,trns_inc_Y_y,trns_line_ptr}

;;        Debug tr,"Calling plotting routine: lx,rx,ty",trns_scr_lx, trns_scr_rx, trns_scr_y
;;        Debug tr,"incXx,Yx,Xy,Yy,lineptr",trns_inc_X_x,trns_inc_Y_x,trns_inc_X_y,trns_inc_Y_y,trns_line_ptr
;;        Debug tr,"X0Y0",trns_X_x0_y,trns_Y_x0_y

        BL      plot_and_calculate_row
        Pull    "R1,R11,R12"
        LDR     R14, linelength
        LDR     trns_line_ptr, trns_spr_lineptr
        ADD     trns_line_ptr, trns_line_ptr, R14
        STR     trns_line_ptr, trns_spr_lineptr
        LDR     trns_X_x0_y, trns_spr_X_x0_y
        LDR     trns_Y_x0_y, trns_spr_Y_x0_y
        LDR     trns_inc_X_y, trns_spr_inc_X_y
        LDR     trns_inc_Y_y, trns_spr_inc_Y_y
        SUB     trns_X_x0_y, trns_X_x0_y, trns_inc_X_y
        SUB     trns_Y_x0_y, trns_Y_x0_y, trns_inc_Y_y
        STR     trns_X_x0_y, trns_spr_X_x0_y
        STR     trns_Y_x0_y, trns_spr_Y_x0_y
        SUB     R1, R1, #1
        B       %BT00

trns_completed_drawing

; Update changed coordinate block?

        LDR     R14, changedbox
        LDR     R0, [R14], #4
        TST     R0, #1
        BEQ     trns_no_changed_box

; Get R6 = top y, R4 = bottom y

        LDR     R6, save_ycoord
        MOV     R4, R1

; Check top y was above gwy0, else no change to box

        LDR     R0, gwy0
        CMP     R6, R0
        BLT     trns_no_changed_box

; Find R3 = left x, R5 = right x

        ADR     R0, trns_spr_xcoords
        LDMIA   R0, {R3,R7,R8,R9}
        MOV     R5, R3
        CMP     R3, R7
        MOVGT   R3, R7
        CMP     R3, R8
        MOVGT   R3, R8
        CMP     R3, R9
        MOVGT   R3, R9
        CMP     R5, R7
        MOVLT   R5, R7
        CMP     R5, R8
        MOVLT   R5, R8
        CMP     R5, R9
        MOVLT   R5, R9

; Now convert from 256ths pixels to pixels, and clip to graphics window

        ADD     R3, R3, #128
        MOV     R3, R3, ASR #8
        ADD     R5, R5, #128
        MOV     R5, R5, ASR #8
        LDR     R0, gwx0
        LDR     R1, gwx1
        CMP     R3, R0
        MOVLT   R3, R0
        CMP     R5, R1
        MOVGT   R5, R1
        CMP     R3, R5
        BGT     trns_no_changed_box

; Unbodge double pixels

        LDR     R7, Log2bpc
        LDR     R8, Log2bpp
Neil Turton's avatar
Neil Turton committed
1311
        SUB     R7, R7, R8
Neil Turton's avatar
Neil Turton committed
1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330
        MOVNE   R3, R3, LSL R7
        MOVNE   R5, R5, LSL R7
        ADD     R4, R4, #1

; Get original box and update it

        LDMIA   R14, {R0,R1,R2,R7}
        CMP     R0, R3
        MOVGT   R0, R3
        CMP     R1, R4
        MOVGT   R1, R4
        CMP     R2, R5
        MOVLT   R2, R5
        CMP     R7, R6
        MOVLT   R7, R6
        STMIA   R14, {R0,R1,R2,R7}

trns_no_changed_box
        ADD     sp, sp, #trns_spr_vars_end
1331 1332
        CLRV
        Pull    "R1-R9,PC"
Neil Turton's avatar
Neil Turton committed
1333

Neil Turton's avatar
Neil Turton committed
1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346

; -------------------------------------------------------------
; - Routine to get increment in sprite due to x or y movement -
; -------------------------------------------------------------
; R0 - x or y distance
; R1 - size of sprite (width or height)
; R6,7 - 64 bit determinant (16.48 format)
; Result in R4

produce_increment
        Push    "R0-R3,R5-R12,R14"
        Debug tr,"Inputs:",R0,R1,R6,R7

Neil Turton's avatar
Neil Turton committed
1347
; First split R6/7 into R4-R7
Neil Turton's avatar
Neil Turton committed
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387

        MOVS    R3, R7, ASR #32
        BEQ     %FT01
        RSBS    R6, R6, #0
        RSC     R7, R7, #0
01
        MOV     R4, R7, LSR #16
        BIC     R5, R7, R4, LSL #16
        MOV     R7, R6, LSR #16
        BIC     R6, R6, R7, LSL #16

; Now check sign of R0, R3 = sign of product

        EORS    R3, R3, R0, ASR #32

; If R3<0 (i.e. product<0) then R1=-R1

        RSBMI   R1, R1, #0

; If R0<0 then R0=-R0

        RSBCS   R0, R0, #0

; Split R0

        MOV     R2, R0, LSR #16
        BIC     R0, R0, R2, LSL #16
        Debug tr,"Premultiply values:R0,R2,R1,R3:",R0,R2,R1,R3
        Debug tr,"Premultiply values:R4,R5,R7,R6:",R4,R5,R7,R6

; Now produce R8 = U0.6 + L2.6 + L0.7, R6 = U2.6 + U0.7 (inc. carries)

        MUL     R8, R0, R6
        MUL     R6, R2, R6
        MUL     R3, R0, R7
        ADDS    R3, R3, R6
        MOV     R6, R3, LSR #16
        ADDCS   R6, R6, #&10000
        ADDS    R8, R8, R3, LSL #16
        MOV     R8, R8, LSR #16
Neil Turton's avatar
Neil Turton committed
1388
        ADC     R6, R6, #0
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
        Debug tr,"Stage 1:R6,R8",R6,R8

; Now produce R9 = L6 + L2.7 + L0.5, R7 = U6 + U2.7 + U0.5 (inc carries)

        MUL     R9, R0, R5
        MUL     R7, R2, R7
        ADDS    R3, R7, R9
        MOV     R7, R3, LSR #16
        ADDCS   R7, R7, #&10000
        ADD     R7, R7, R6, LSR #16
        MOV     R9, R3, LSL #16
        ADDS    R9, R9, R6, LSL #16
        MOV     R9, R9, LSR #16
        ADC     R7, R7, #0
        Debug tr,"Stage 2:R7,R9",R7,R9

; Now produce R10 = L7 + L2.5 + L0.4, R5 = U7 + U2.5 + U0.4 (inc. carries)

        MUL     R10, R0, R4
        MUL     R5, R2, R5
        ADDS    R3, R5, R10
        MOV     R5, R3, LSR #16
        ADDCS   R5, R5, #&10000
        ADD     R5, R5, R7, LSR #16
        MOV     R10, R3, LSL #16
        ADDS    R10, R10, R7, LSL #16
        MOV     R10, R10, LSR #16
        ADC     R5, R5, #0
        Debug tr,"Stage 3:R10,R5",R10,R5

; Now produce R11 = L5 + L2.4

        MLA     R11, R2, R4, R5
        MOV     R3, R11, LSR #16
        BIC     R11, R11, R3, LSL #16

; Now R11.R10.R9.R8 (sixteen bits each) = 256/Det*Size in 32.32 form
; So get R1 * R11.R10.R9.R8 into R4

        MUL     R8, R1, R8
        MUL     R9, R1, R9
        MUL     R10, R1, R10
        MUL     R11, R1, R11
        MOV     R4, R8, ASR #24
        ADD     R4, R4, R9, ASR #8
        ADD     R4, R4, R10, ASL #8
        ADD     R4, R4, R11, ASL #24

        ;bug fix, round up if necessary
        TST     R9,#&80
        ADDNE   R4,R4,#1

        Debug tr,"Output:R4",R4

1443
        Pull    "R0-R3,R5-R12,PC"
Neil Turton's avatar
Neil Turton committed
1444 1445 1446 1447 1448



; -----------------------------------
; - DrQfill routines required above -
Neil Turton's avatar
Neil Turton committed
1449
; -----------------------------------
Neil Turton's avatar
Neil Turton committed
1450 1451 1452 1453 1454
; Fast Y clipping routine

out_qfill_fastclip
        Push    "R1,R2,R7,LR"
        MOV     R7,R6,ASR #31           ;Sign-extend Bresenham value
Kevin Bracey's avatar
Kevin Bracey committed
1455
        SSmultD R8,R3,R1,R2             ;(no. Y steps) * deltaX into R1,R2
Neil Turton's avatar
Neil Turton committed
1456 1457 1458 1459 1460 1461
        ADDS    R6,R6,R1                ;Accumulate into Bresenham value
        ADCS    R7,R7,R2
        MOVMI   R8,#0                   ;Check for still being to the right
        BMI     out_qfill_fastclipdone  ;  of the edge
        BL      arith_DSdivS            ;Divide by deltaY
        DCB     R6,R4,R8,0
Kevin Bracey's avatar
Kevin Bracey committed
1462
        SSmultD R8,R4,R1,R2             ;(no. X steps) * deltaY into R1,R2
Neil Turton's avatar
Neil Turton committed
1463 1464 1465
        SUB     R6,R6,R1                ;Not interested in high word!

out_qfill_fastclipdone
1466
        Pull    "R1,R2,R7,LR"
Neil Turton's avatar
Neil Turton committed
1467 1468 1469
        TEQ     R0,#0                   ;Move X co-ord. in right direction
        ADDPL   R7,R7,R8
        SUBMI   R7,R7,R8
1470
        MOV     PC,LR
Neil Turton's avatar
Neil Turton committed
1471 1472 1473 1474 1475 1476 1477 1478 1479 1480

; Subroutine to advance an edge horizontally fast (i.e. using long division
; rather than division by repeated subtraction!)
;   Updates R6 and R7, corrupts R2 and R3, preserves flags & other registers

out_qfill_fasthoriz
        DivRem  R2,R6,R4,R3
        TEQ     R0,#0
        ADDPL   R7,R7,R2
        SUBMI   R7,R7,R2
1481
        MOV     PC,LR
Neil Turton's avatar
Neil Turton committed
1482

Kevin Bracey's avatar
Kevin Bracey committed
1483
 [ :LNOT:usemull
Neil Turton's avatar
Neil Turton committed
1484 1485 1486 1487 1488 1489 1490 1491
; Subroutine to multiply two single precision signed numbers together and
; get a double precision result. The word following the BL should contain
; the numbers of the two operand registers in its bottom two bytes and the
; number of the register to take the ls part of the result in the next byte.
; The ms part of the result will go into the next register.
;   This routine will only work on registers R0-R8.

arith_SSmultD
1492 1493 1494
        Push    "R0-R8"                 ;REMEMBER: need to stack R0-R8 so they can hold results
        RSB     R8,PC,PC                ;get embedded PSR flags into R8 - 26/32-bit mode neutral
        LDRB    R0,[R14,-R8]!           ;Get first operand; R14 := (R14 - PSR)
Neil Turton's avatar
Neil Turton committed
1495
        LDR     R0,[R13,R0,LSL #2]
1496
        LDRB    R1,[R14,#1]             ;Get second operand
Neil Turton's avatar
Neil Turton committed
1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513
        LDR     R1,[R13,R1,LSL #2]
        MOV     R4,R0,LSR #16           ;Split first operand into halves
        BIC     R3,R0,R4,LSL #16
        MOVS    R6,R1,LSR #16           ;Split second operand into halves
        BIC     R5,R1,R6,LSL #16
        MUL     R2,R3,R5                ;Produce low partial product
        MUL     R3,R6,R3                ;And middle partial products
        MUL     R5,R4,R5
        MULNE   R6,R4,R6                ;And high partial product
        ADDS    R3,R3,R5                ;Add middle partial products, dealing
        ADDCS   R6,R6,#&10000           ;  with overflow
        ADDS    R2,R2,R3,LSL #16        ;Add middle partial product sum into
        ADC     R6,R6,R3,LSR #16        ;  result
        TEQ     R0,#0                   ;Add cross products of operands and
        SUBMI   R6,R6,R1                ;  operand sign extensions into
        TEQ     R1,#0                   ;  result
        SUBMI   R6,R6,R0
1514
        LDRB    R0,[R14,#2]             ;Store the result on the stack, to be
Neil Turton's avatar
Neil Turton committed
1515 1516 1517
        ADD     R0,R13,R0,LSL #2        ;  picked up by the correct registers
        STMIA   R0,{R2,R6}
        Pull    "R0-R8"
1518
        ADD     PC,R14,#4               ;Skip the argument word on return (don't use ADDS!)
Kevin Bracey's avatar
Kevin Bracey committed
1519
 ]
Neil Turton's avatar
Neil Turton committed
1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532

; Subroutine to divide a double precision unsigned number by a single
; precision unsigned number, yielding a single precision unsigned result.
; The word following the BL should contain the number of the register holding
; the ls part of the dividend in its bottom byte; the ms part of the dividend
; is in the next register. The next byte of the word contains the number of
; the divisor register, and the next byte the number of the register in which
; to deposit the quotient.
;   This routine will only work on registers R0-R8. It assumes that the
; divisor is not zero, and that the quotient will not overflow.

arith_DSdivS
        Push    "R0-R8"
1533 1534
        RSB     R8,PC,PC                ;get embedded PSR flags into R8 - 26/32-bit mode neutral
        LDRB    R0,[R14,-R8]!           ;Get first operand; R14 := (R14 - PSR)
Neil Turton's avatar
Neil Turton committed
1535 1536
        ADD     R0,R13,R0,LSL #2
        LDMIA   R0,{R0,R1}
1537
        LDRB    R2,[R14,#1]             ;Get second operand
Neil Turton's avatar
Neil Turton committed
1538 1539 1540 1541 1542 1543 1544 1545 1546 1547
        LDR     R2,[R13,R2,LSL #2]
        MOV     R3,#1                   ;Init. quotient with a sentinel bit

arith_DSdivS_loop
        ADDS    R0,R0,R0                ;Shift a bit up into the ms half of
        ADC     R1,R1,R1                ;  the dividend
        CMP     R1,R2                   ;Do trial subtraction, producing
        SUBCS   R1,R1,R2                ;  result bit in C
        ADCS    R3,R3,R3                ;Result bit into result, then loop
        BCC     arith_DSdivS_loop       ;  unless sentinel bit shifted out
1548
        LDRB    R0,[R14,#2]             ;Store the result on the stack, to be
Neil Turton's avatar
Neil Turton committed
1549 1550
        STR     R3,[R13,R0,LSL #2]      ;  picked up by the correct registers
        Pull    "R0-R8"
1551
        ADD     PC,R14,#4               ;Skip the argument word on return (don't use ADDS!)
Neil Turton's avatar
Neil Turton committed
1552 1553 1554 1555 1556 1557 1558 1559 1560


;       ---------------------------------
;       - The code which is compiled in -
;       ---------------------------------
compiled_routine_stacked        *       calc_row_stacked + 1*4 - 4; Number of bytes stacked since main loop

;                       Start of routine
trnslp_strt
1561
        Push    "R14"
Neil Turton's avatar
Neil Turton committed
1562 1563 1564
        MOV     trns_out_word, #&80000000
        MOV     trns_out_mask, #0
        CMP     trns_xsize, #0
1565
        Pull    "PC",LE
Neil Turton's avatar
Neil Turton committed
1566 1567
trnslp_strt_size        *       .-trnslp_strt
        ASSERT (trnslp_strt_size) = 5*4
Neil Turton's avatar
Neil Turton committed
1568

Neil Turton's avatar
Neil Turton committed
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
;                       Get address of lefthand x on screen (dependent on out_bpp)
trnslp_getaddr_o1
        ADD     trns_out_ptr, trns_out_ptr, trns_out_x, LSR# 3 ;(0.1.2.3 - 8.4.2.1 out_bpp)
        BIC     trns_out_ptr, trns_out_ptr, #3
        AND     trns_out_x, trns_out_x, #31                     ;(3.7.15.31 - 8.4.2.1 out_bpp)
        ANDEQ   R0,R0,R0
trnslp_getaddr_o2
        ADD     trns_out_ptr, trns_out_ptr, trns_out_x, LSR# 2 ;(0.1.2.3 - 8.4.2.1 out_bpp)
        BIC     trns_out_ptr, trns_out_ptr, #3
        MOV     trns_out_x, trns_out_x, LSL#1
        AND     trns_out_x, trns_out_x, #30                     ;(3.7.15.31 - 8.4.2.1 out_bpp)
trnslp_getaddr_o4
        ADD     trns_out_ptr, trns_out_ptr, trns_out_x, LSR# 1  ;(0.1.2.3 - 8.4.2.1 out_bpp)
        BIC     trns_out_ptr, trns_out_ptr, #3
        MOV     trns_out_x, trns_out_x, LSL#2
        AND     trns_out_x, trns_out_x, #28                     ;(3<<3.7<<2.15<<1.31<<0 - 8.4.2.1 out_bpp)
trnslp_getaddr_o8
        ADD     trns_out_ptr, trns_out_ptr, trns_out_x          ;(0.1.2.3 - 8.4.2.1 out_bpp)
        BIC     trns_out_ptr, trns_out_ptr, #3
        MOV     trns_out_x, trns_out_x, LSL#3
        AND     trns_out_x, trns_out_x, #24                     ;(3.7.15.31 - 8.4.2.1 out_bpp)
trnslp_getaddr_o16
        ADD     trns_out_ptr, trns_out_ptr, trns_out_x, LSL #1
        BIC     trns_out_ptr, trns_out_ptr, #3
        MOV     trns_out_x, trns_out_x, LSL #4
Neil Turton's avatar
Neil Turton committed
1594
        AND     trns_out_x, trns_out_x, #16
Neil Turton's avatar
Neil Turton committed
1595 1596 1597 1598
trnslp_getaddr_o24
        ADD     trns_out_ptr, trns_out_ptr, trns_out_x, LSL #2
        BIC     trns_out_ptr, trns_out_ptr, #3
        MOV     trns_out_x, trns_out_x, LSL#5
Neil Turton's avatar
Neil Turton committed
1599
        AND     trns_out_x, trns_out_x, #0
Neil Turton's avatar
Neil Turton committed
1600 1601
trnslp_getaddr_size     *       .-trnslp_getaddr_o24
        ASSERT (.-trnslp_getaddr_o1) = 6*trnslp_getaddr_size
Neil Turton's avatar
Neil Turton committed
1602

Neil Turton's avatar
Neil Turton committed
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
;                       Get pixel and macro word shifted to align with lefthand pixel inside screen word
trnslp_getwam
        MOV     trns_out_word, trns_out_word, LSR trns_out_x
trnslp_getwam_size      *       .-trnslp_getwam
        ASSERT (trnslp_getwam_size) = 1*4

;                       Start of loop
trnslp_stloop1
        MOVS    trns_offset, trns_Y, ASR#16
        MOVMI   trns_offset, #0
        MOV     trns_dummy14, trns_spr_height, LSR#16
        CMP     trns_dummy14, trns_Y, ASR#16
trnslp_stloop1_size      *       .-trnslp_stloop1
trnslp_stloop2
        SUBLE   trns_offset, trns_dummy14, #1
        MUL     trns_offset, trns_byte_width, trns_offset
        MOV     trns_dummy14, trns_X
        CMP     trns_X, trns_spr_left, LSL #16
trnslp_stloop2_size      *       .-trnslp_stloop2
trnslp_stloop3
        MOVLT   trns_dummy14, trns_spr_left, LSL #16
        CMP     trns_X, trns_spr_right, LSL #16
        MOVGE   trns_dummy14, trns_spr_right, LSL #16
        SUBGE   trns_dummy14, trns_dummy14, #1
        ADD     trns_offset, trns_offset, trns_dummy14, LSR #16
trnslp_stloop3_size      *       .-trnslp_stloop3

;                       Start of loop (1bpp mask)
trnslp_nmstloop1
        MOVS    trns_offset, trns_Y, ASR#16
        MOVMI   trns_offset, #0
        MOV     trns_dummy14, trns_spr_height, LSR#16
        CMP     trns_dummy14, trns_Y, ASR#16
trnslp_nmstloop1_size      *       .-trnslp_nmstloop1
trnslp_nmstloop2
        SUBLE   trns_offset, trns_dummy14, #1
        LDR     trns_dummy12, trns_comp_spr_mask_width + compiled_routine_stacked
        MUL     trns_dummy12, trns_offset, trns_dummy12
        MUL     trns_offset, trns_byte_width, trns_offset
        MOV     trns_dummy14, trns_X
trnslp_nmstloop2_size      *       .-trnslp_nmstloop2
trnslp_nmstloop3
        CMP     trns_X, trns_spr_left, LSL #16
        MOVLT   trns_dummy14, trns_spr_left, LSL #16
        CMP     trns_X, trns_spr_right, LSL #16
        MOVGE   trns_dummy14, trns_spr_right, LSL #16
        SUBGE   trns_dummy14, trns_dummy14, #1
trnslp_nmstloop3_size      *       .-trnslp_nmstloop3
trnslp_nmstloop4
        ADD     trns_offset, trns_offset, trns_dummy14, LSR #16
        ADD     trns_dummy12, trns_dummy12, trns_dummy14, LSR #16
        STR     trns_dummy12, trns_comp_mask_offset + compiled_routine_stacked
trnslp_nmstloop4_size      *       .-trnslp_nmstloop4


;                       Shift pixel and mask words by out_bpp
trnslp_shfwam_o1
        MOVS    trns_out_word, trns_out_word, LSR#1
        MOV     trns_out_mask, trns_out_mask, LSR#1
trnslp_shfwam_o2
        MOVS    trns_out_word, trns_out_word, LSR#2
        MOV     trns_out_mask, trns_out_mask, LSR#2
trnslp_shfwam_o4
        MOVS    trns_out_word, trns_out_word, LSR#4
        MOV     trns_out_mask, trns_out_mask, LSR#4
trnslp_shfwam_o8
        MOVS    trns_out_word, trns_out_word, LSR#8
        MOV     trns_out_mask, trns_out_mask, LSR#8
trnslp_shfwam_o16
        MOVS    trns_out_word, trns_out_word, LSR#16
        MOV     trns_out_mask, trns_out_mask, LSR#16
trnslp_shfwam_o24
        ;MOVS    trns_out_word, trns_out_word
Neil Turton's avatar
Neil Turton committed
1676
        ;MOV     trns_out_mask, trns_out_mask
Neil Turton's avatar
Neil Turton committed
1677 1678
        ;achieve the same effect as a LSR#32 would do, if such existed!
        MOV      trns_out_word,#1
Neil Turton's avatar
Neil Turton committed
1679
        MOVS     trns_out_word,trns_out_word,LSR #1
Neil Turton's avatar
Neil Turton committed
1680 1681
trnslp_shfwam_size      *       .-trnslp_shfwam_o24
        ASSERT (.-trnslp_shfwam_o1) = trnslp_shfwam_size*6
Neil Turton's avatar
Neil Turton committed
1682

Neil Turton's avatar
Neil Turton committed
1683 1684 1685 1686 1687 1688 1689 1690 1691 1692
;can't do the 32 bit case in two instructions, so here's the last one

trnslp_shfwam_o24_2
        MOV      trns_out_mask, #0

;                       Read pixel from sprite (dependent on in_bpp)
trnslp_readpx_i1
        LDRB    trns_dummy14, [trns_spr_start, trns_offset, LSR #3]     ;(0.1.2.3 - 8.4.2.1 in_bpp)
        AND     trns_dummy12, trns_offset, #7                           ;(0.1.3.7 - 8.4.2.1 in_bpp)
        MOV     trns_dummy14, trns_dummy14, LSR trns_dummy12
Neil Turton's avatar
Neil Turton committed
1693
        AND     trns_dummy14, trns_dummy14, #&1                         ;(&FF.&F.&3.&1 - 8.4.2.1 in_bpp)
Neil Turton's avatar
Neil Turton committed
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713
trnslp_readpx_i1_size * .-trnslp_readpx_i1
        ANDEQ   R0,R0,R0
trnslp_readpx_i2
        LDRB    trns_dummy14, [trns_spr_start, trns_offset, LSR #2]     ;(0.1.2.3 - 8.4.2.1 in_bpp)
        AND     trns_dummy12, trns_offset, #3                           ;(0.1.3.7 - 8.4.2.1 in_bpp)
        MOV     trns_dummy12, trns_dummy12, LSL#1                       ;(3.2.1.0 - 8.4.2.1 in_bpp)
        MOV     trns_dummy14, trns_dummy14, LSR trns_dummy12
        AND     trns_dummy14, trns_dummy14, #&3                         ;(&FF.&F.&3.&1 - 8.4.2.1 in_bpp)
trnslp_readpx_i4
        LDRB    trns_dummy14, [trns_spr_start, trns_offset, LSR #1]     ;(0.1.2.3 - 8.4.2.1 in_bpp)
        AND     trns_dummy12, trns_offset, #1                           ;(0.1.3.7 - 8.4.2.1 in_bpp)
        MOV     trns_dummy12, trns_dummy12, LSL#2                       ;(3.2.1.0 - 8.4.2.1 in_bpp)
        MOV     trns_dummy14, trns_dummy14, LSR trns_dummy12
        AND     trns_dummy14, trns_dummy14, #&F                         ;(&FF.&F.&3.&1 - 8.4.2.1 in_bpp)
trnslp_readpx_i8
        LDRB    trns_dummy14, [trns_spr_start, trns_offset]
        ANDEQ   R0,R0,R0
        ANDNE   R0,R0,R0
        ANDNE   R0,R0,R0
        ANDEQ   R0,R0,R0
Neil Turton's avatar
Neil Turton committed
1714
trnslp_readpx_i16
Neil Turton's avatar
Neil Turton committed
1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728
        ;note - this will be word or half word aligned
        LDR     trns_dummy14, [trns_spr_start, trns_offset, LSL #1]
        MOV     trns_dummy14, trns_dummy14, LSL #16
        MOV     trns_dummy14, trns_dummy14, LSR #16
        ANDNE   R0,R0,R0
        ANDEQ   R0,R0,R0
trnslp_readpx_i32
        LDR     trns_dummy14, [trns_spr_start, trns_offset, LSL #2]
        ANDEQ   R0,R0,R0
        ANDNE   R0,R0,R0
        ANDNE   R0,R0,R0
        ANDEQ   R0,R0,R0
trnslp_readpx_size      *       trnslp_readpx_i8-trnslp_readpx_i4
        ASSERT (.-trnslp_readpx_i1) = trnslp_readpx_size*6
Neil Turton's avatar
Neil Turton committed
1729

Neil Turton's avatar
Neil Turton committed
1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750
;                       Translate pixel through ttr
trnslp_transpx
        LDR     trns_dummy12, trns_comp_spr_ttr + compiled_routine_stacked
        LDRB    trns_dummy14, [trns_dummy12, trns_dummy14]
trnslp_transpx_size      *      .-trnslp_transpx
        ASSERT (trnslp_transpx_size) = 2*4

trnslp_transpx1
        LDR     trns_dummy12, trns_comp_spr_ttr + compiled_routine_stacked
        LDR     trns_dummy14, [trns_dummy12, trns_dummy14, LSL #2]
trnslp_transpx1_size    *       .-trnslp_transpx1

        [ ignore_ttr
trnslp_transpx2
        LDR     trns_dummy12, trns_comp_spr_ttr + compiled_routine_stacked
        LDR     trns_dummy14, [trns_dummy12, trns_dummy14, LSL #3]
        MOV     trns_dummy14, trns_dummy14, LSR #8 ;now in correct form for 32bpp
trnslp_transpx2_size    *       .-trnslp_transpx2
        ;use trnslp_munge_32to16 if doing 16bpp
        ]

Neil Turton's avatar
Neil Turton committed
1751
trnslp_use32K
Neil Turton's avatar
Neil Turton committed
1752 1753 1754 1755
       MOV      trns_dummy14,trns_dummy14,LSL #17
       MOV      trns_dummy14,trns_dummy14,LSR #17

       LDR      trns_dummy12,trns_comp_spr_ttr + compiled_routine_stacked ;fetch the table address
Neil Turton's avatar
Neil Turton committed
1756
       LDR      trns_dummy12,[trns_dummy12,#4]
Neil Turton's avatar
Neil Turton committed
1757 1758
       ; trns_dummy12 is correct at this point....
       LDRB     trns_dummy14,[trns_dummy12,trns_dummy14]
Neil Turton's avatar
Neil Turton committed
1759
trnslp_use32K_size      *      .-trnslp_use32K
Neil Turton's avatar
Neil Turton committed
1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794

;                       Copy pixel into output word (dependent on out_bpp)
trnslp_setpx
        ORR     trns_out_word, trns_out_word, trns_dummy14, LSL #xxx
trnslp_setpx_size       *       .-trnslp_setpx
        ASSERT (trnslp_setpx_size) = 1*4

;                       If sprite has no mask, then ORR set bits into the output mask word
trnslp_sprnomask_o1
        ORR     trns_out_mask, trns_out_mask, #&80000000
trnslp_sprnomask_o2
        ORR     trns_out_mask, trns_out_mask, #&C0000000
trnslp_sprnomask_o4
        ORR     trns_out_mask, trns_out_mask, #&F0000000
trnslp_sprnomask_o8
        ORR     trns_out_mask, trns_out_mask, #&FF000000
trnslp_sprnomask_size   *       .-trnslp_sprnomask_o8
        ASSERT (.-trnslp_sprnomask_o1) = trnslp_sprnomask_size*4

trnslp_sprnomask16or24
        LDR     trns_dummy14, trns_masking_word +compiled_routine_stacked
        ORR     trns_out_mask, trns_out_mask, trns_dummy14
trnslp_sprnomask16or24_size * .-trnslp_sprnomask16or24
        ASSERT  trnslp_sprnomask16or24_size = 4*2
;                       If sprite has a mask then read it in (also uses trnslp_readpx_i, above)
trnslp_sprmask
        LDR     trns_dummy14, trns_comp_spr_masko + compiled_routine_stacked
        ADD     trns_offset, trns_offset, trns_dummy14
trnslp_sprmask_size     *       .-trnslp_sprmask
        ASSERT (trnslp_sprmask_size) = 2*4

;                       If sprite has a 1BPP mask then read it in
; (note: no longer uses trnslp_readpx_i1 - it needs a different base address and must
; preserve the original one by avoiding trns_spr_start (R1) )

Neil Turton's avatar
Neil Turton committed
1795
trnslp_new_sprmask
Neil Turton's avatar
Neil Turton committed
1796 1797 1798 1799 1800
        ;
        LDR     trns_dummy12, trns_comp_mask_base + compiled_routine_stacked
        LDR     trns_offset, trns_comp_mask_offset + compiled_routine_stacked
        LDRB    trns_dummy14,[trns_dummy12, trns_offset, LSR #3]
trnslp_new_sprmask_size     *       .-trnslp_new_sprmask
Neil Turton's avatar
Neil Turton committed
1801
trnslp_new_sprmask2
Neil Turton's avatar
Neil Turton committed
1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821
        AND     trns_dummy12, trns_offset, #7
        MOV     trns_dummy14, trns_dummy14, LSR trns_dummy12
        AND     trns_dummy14, trns_dummy14, #1
trnslp_new_sprmask2_size     *       .-trnslp_new_sprmask2

;                       Setup valid mask pixel into mask word
trnslp_setmask_o1
        TEQ     trns_dummy14, #0                ;Is the mask pixel set?
        ORRNE   trns_out_mask, trns_out_mask, #&80000000
trnslp_setmask_o2
        TEQ     trns_dummy14, #0                ;Is the mask pixel set?
        ORRNE   trns_out_mask, trns_out_mask, #&C0000000
trnslp_setmask_o4
        TEQ     trns_dummy14, #0                ;Is the mask pixel set?
        ORRNE   trns_out_mask, trns_out_mask, #&F0000000
trnslp_setmask_o8
        TEQ     trns_dummy14, #0                ;Is the mask pixel set?
        ORRNE   trns_out_mask, trns_out_mask, #&FF000000
trnslp_setmask_size * .-trnslp_setmask_o8
        ASSERT  (.-trnslp_setmask_o1) = trnslp_setmask_size*4
Neil Turton's avatar
Neil Turton committed
1822

Neil Turton's avatar
Neil Turton committed
1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834
trnslp_setmask16or24
        TEQ     trns_dummy14, #0                ;Is the mask pixel set?
        LDRNE   trns_dummy14, trns_masking_word +compiled_routine_stacked
        ORRNE   trns_out_mask, trns_out_mask, trns_dummy14
trnslp_setmask16or24_size * .-trnslp_setmask16or24
        ASSERT  (.-trnslp_setmask16or24) = 3*4

;                       Cope with 1:1 mapping in the mask and screen mode
trnslp_setmask2
        ORR     trns_out_mask, trns_out_mask, trns_dummy14, LSL #xxx
trnslp_setmask2_size    *       .-trnslp_setmask2
        ASSERT (trnslp_setmask2_size) = 1*4
Neil Turton's avatar
Neil Turton committed
1835

Neil Turton's avatar
Neil Turton committed
1836 1837 1838 1839 1840 1841
;                       Read the screen word
trnslp_readscrn
        LDRCS   trns_offset, [trns_out_ptr]
        ANDCS   trns_out_word, trns_out_word, trns_out_mask
trnslp_readscrn_size    *       .-trnslp_readscrn
        ASSERT (trnslp_readscrn_size) = 2*4
Neil Turton's avatar
Neil Turton committed
1842

1843 1844 1845 1846 1847 1848 1849 1850
 [ AvoidScreenReads
trnslp_readscrn0
        MVNS    trns_offset, trns_out_mask      ; Z set iff out_mask is all 1s
        LDRHI   trns_offset, [trns_out_ptr]     ; load if C set & Z clear
        ANDCS   trns_out_word, trns_out_word, trns_out_mask
trnslp_readscrn0_size   *       .-trnslp_readscrn0
 ]

Neil Turton's avatar
Neil Turton committed
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
;                       Effect the screen word depending on the GCOL action
trnslp_gcol
;      GCOL 0 - plot direct
                BICCS   trns_offset, trns_offset, trns_out_mask
                EORCS   trns_offset, trns_offset, trns_out_word
;      GCOL 1 - OR with screen
                ORRCS   trns_offset, trns_offset, trns_out_word
        ANDEQ   R0,R0,R0
;      GCOL 2 - AND with screen
                EORCS   trns_out_word, trns_out_word, trns_out_mask
                BICCS   trns_offset, trns_offset, trns_out_word
;      GCOL 3 - EOR with screen
                EORCS   trns_offset, trns_offset, trns_out_word
        ANDEQ   R0,R0,R0
;      GCOL 4 - Invert screen
                EORCS   trns_offset, trns_offset, trns_out_mask
        ANDEQ   R0, R0, R0
;      GCOL 5 - Do nothing
        ANDEQ   R0,R0,R0
        ANDEQ   R0,R0,R0
;      GCOL 6 - AND with NOT colour
                BICCS   trns_offset, trns_offset, trns_out_word
        ANDEQ   R0,R0,R0
;      GCOL 7 - ORR with NOT colour
                EORCS   trns_out_word, trns_out_word, trns_out_mask
                ORRCS   trns_offset, trns_offset, trns_out_word
trnslp_gcol_size        *       2*4
        ASSERT (.-trnslp_gcol) = trnslp_gcol_size * 8
Neil Turton's avatar
Neil Turton committed
1879

Neil Turton's avatar
Neil Turton committed
1880
;                       Effect the screen word according to the mask and ECF
Neil Turton's avatar
Neil Turton committed
1881
trnslp_plotmask
Neil Turton's avatar
Neil Turton committed
1882 1883 1884 1885 1886 1887 1888 1889
                LDRCS   trns_dummy12, trns_comp_ecf_ora + compiled_routine_stacked
                LDRCS   trns_out_word, trns_comp_ecf_eor + compiled_routine_stacked
                ANDCS   trns_dummy12, trns_dummy12, trns_out_mask
                ANDCS   trns_out_word, trns_out_word, trns_out_mask
                ORRCS   trns_offset, trns_offset, trns_dummy12
                EORCS   trns_offset, trns_offset, trns_out_word
trnslp_plotmask_size    *       .-trnslp_plotmask
        ASSERT (trnslp_plotmask_size) = 6*4
Neil Turton's avatar
Neil Turton committed
1890

Neil Turton's avatar
Neil Turton committed
1891 1892 1893 1894 1895 1896 1897 1898 1899 1900
;                       End of the loop - store the screen word and move on a screen pixel
trnslp_eoloop
                STRCS   trns_offset, [trns_out_ptr], #4
                MOVCS   trns_out_word, #&80000000
                ADD     trns_X, trns_X, trns_inc_X_x
                ADD     trns_Y, trns_Y, trns_inc_Y_x
                SUB     trns_xsize, trns_xsize, #&10000
                CMP     trns_xsize, #&10000
trnslp_eoloop_size      *       .-trnslp_eoloop
        ASSERT (trnslp_eoloop_size) = 6*4
Neil Turton's avatar
Neil Turton committed
1901

Neil Turton's avatar
Neil Turton committed
1902 1903 1904
;                       Finished row so store last compiled output word and mask, if necessary
trnslp_lastword
        CMP     trns_out_word, #&80000000
1905
        LDMEQFD sp!, {PC}
Neil Turton's avatar
Neil Turton committed
1906 1907
trnslp_lastword_size        *       .-trnslp_lastword
        ASSERT (trnslp_lastword_size) = 2*4
Neil Turton's avatar
Neil Turton committed
1908

Neil Turton's avatar
Neil Turton committed
1909 1910 1911
;                       Stored last output word and mask on screen, so exit
trnslp_lastword2
        STR     trns_offset, [trns_out_ptr]
1912
        LDMFD   sp!, {PC}
Neil Turton's avatar
Neil Turton committed
1913 1914 1915
trnslp_lastword2_size        *       .-trnslp_lastword2
        ASSERT (trnslp_lastword2_size) = 2*4

Neil Turton's avatar
Neil Turton committed
1916
trnslp_munge_16to321
Neil Turton's avatar
Neil Turton committed
1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933
        Push    "R0,R2"
                                          ;      fedcba9876543210 fedcba9876543210
                                          ; LR =                  0bbbbbgggggrrrrr
        MOV     R0,trns_dummy14,LSR #10   ; R0 =                            0bbbbb
        MOV     R2,R0,LSL #19             ; R2 =        0bbbbb000 0000000000000000
        AND     R0,trns_dummy14,#&3E0     ; R0 =                  000000ggggg00000
        ORR     R2,R2,R0,LSL #6           ; R2 =        0bbbbb000 ggggg00000000000
trnslp_m1632_size1        *       .-trnslp_munge_16to321
trnslp_munge_16to322
        MOV     R0,trns_dummy14,LSL #27   ; R0 = rrrrr00000000000 0000000000000000
        ORR     R2,R2,R0,LSR #24          ; R2 =        0bbbbb000 ggggg000rrrrr000

        ;now copy the top three bits of each colour component into the bottom three

        MOV     R0,#&E0                   ;avoid an LDR for speed
        ORR     R0,R0,R0,LSL #8
trnslp_m1632_size2        *       .-trnslp_munge_16to322
Neil Turton's avatar
Neil Turton committed
1934
trnslp_munge_16to323
Neil Turton's avatar
Neil Turton committed
1935 1936 1937
        ORR     R0,R0,R0,LSL #8           ; R0 = 0000000011100000 1110000011100000
        AND     R0,R0,R2                  ; R0 = 00000000bbb00000 ggg00000rrr00000
        ORR     trns_dummy14,R2,R0,LSR #5 ; LR = 00000000bbbbbbbb ggggggggrrrrrrrr
Neil Turton's avatar
Neil Turton committed
1938
        Pull    "R0,R2"
Neil Turton's avatar
Neil Turton committed
1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956
trnslp_m1632_size3        *       .-trnslp_munge_16to323

trnslp_munge_32to161
        Push    "R0,R2"
                                             ;      fedcba9876543210 fedcba9876543210
                                             ; LR = 00000000bbbbbbbb ggggggggrrrrrrrr
        AND     R0,trns_dummy14,#&F80000     ; R0 = 00000000bbbbb000 0000000000000000
        MOV     R2,R0,LSR #9                 ; R2 =                  0bbbbb0000000000
        AND     R0,trns_dummy14,#&F800       ; R0 = 0000000000000000 ggggg00000000000
trnslp_m3216_size1        *       .-trnslp_munge_32to161
trnslp_munge_32to162
        ORR     R2,R2,R0,LSR #6              ; R2 =                  0bbbbbggggg00000
        AND     R0,trns_dummy14,#&F8         ; R0 = 0000000000000000 00000000rrrrr000
        ORR     trns_dummy14,R2,R0,LSR #3    ; LR =                  0bbbbbgggggrrrrr

        Pull    "R0,R2"
trnslp_m3216_size2        *       .-trnslp_munge_32to162

Neil Turton's avatar
Neil Turton committed
1957

Neil Turton's avatar
Neil Turton committed
1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969
; ---------------------------------------------
; - Routine to compile the code specified by  -
; - the GCOL action, in_bpp, out_bpp          -
; - translation table, and plotmask/putsprite -
; - options                                   -
; ---------------------------------------------
compile_transform_code
        Push    "LR"
; R11 = GCOL calue (including mask bit)
        AND     R11,R5,#mc_gcol:OR:mc_hasmask
; Set mc_ttr if colour translation table is to be used
        CMP     R7,#0
1970
        ORRNE   R11,R11,#mc_ttr
Neil Turton's avatar
Neil Turton committed
1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987
; Set mc_plotmask if plotting the mask, clear if putting a sprite
        LDR     R14,spritecode
        AND     R14,R14,#&FF
        TEQ     R14,#SpriteReason_PlotMaskTransformed
        ORREQ   R11,R11,#mc_plotmask
; Store the sprite type, so that new masks make a difference
        LDR     R0, save_spr_type
        ORR     R11, R11, R0, LSL #mcb_sprtype

; Set in_bpp, out_bpp
        LDR     R0,save_inbpp
        ORR     R11,R11,R0,LSL #mcb_inbpp
        LDR     R1,BPP
        ORR     R11,R11,R1,LSL #mcb_outbpp

; Set bit denoting transformed sprite, rather than scaled sprite (uses same area as Sprite_PutSpriteScaled)
        ORR     R11, R11, #mc_transformed
Neil Turton's avatar
Neil Turton committed
1988
; Test with old compiled routine
Neil Turton's avatar
Neil Turton committed
1989 1990 1991 1992
        LDR     R14,macroword
        TEQ     R11,R14
        BEQ     trns_compiling_complete
;
Neil Turton's avatar
Neil Turton committed
1993
        STR     R11,macroword
Neil Turton's avatar
Neil Turton committed
1994 1995 1996 1997

; compile the code - R0=in_bpp, R1=out_bpp
        LDR     R0, save_inlog2bpp
        LDR     R1, Log2bpp
Neil Turton's avatar
Neil Turton committed
1998
        ADR     R10, codebuffer
Neil Turton's avatar
Neil Turton committed
1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010
        Debug   mc,"Transformation code starts at",R10

;      Start of loop
                TrnsAsm         trnslp_strt, trnslp_strt_size
;      Get start pixel on the screen line of lefthand x coord (4 instr)
                ADRL            R2, trnslp_getaddr_o1
                ADD             R2, R2, R1, LSL#4
                TrnsAsmReg      R2, trnslp_getaddr_size
                ASSERT trnslp_getaddr_size = 4*4
;      Shift start words (pixel and mask) according to pixel offset
                TrnsAsm         trnslp_getwam, trnslp_getwam_size
; loop Store address on stack for the loop
Neil Turton's avatar
Neil Turton committed
2011 2012
                Push            "R10"

Neil Turton's avatar
Neil Turton committed
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
; If using a 1bpp mask we need to work out a different offset for the mask too
                MOVS            R2, R11, LSR #mcb_sprtype
                TSTNE           R11, #mc_hasmask

;      First 15 words of the loop (to find byte offset in sprite from sprite X,Y coords)
                TrnsAsm         trnslp_stloop1, trnslp_stloop1_size ,EQ
                TrnsAsm         trnslp_stloop2, trnslp_stloop2_size ,EQ
                TrnsAsm         trnslp_stloop3, trnslp_stloop3_size ,EQ

                TrnsAsm         trnslp_nmstloop1, trnslp_nmstloop1_size ,NE
                TrnsAsm         trnslp_nmstloop2, trnslp_nmstloop2_size ,NE
                TrnsAsm         trnslp_nmstloop3, trnslp_nmstloop3_size ,NE
                TrnsAsm         trnslp_nmstloop4, trnslp_nmstloop4_size ,NE

;      Shift pixel and mask words by output bpp (2 instructions)
                ADRL            R2, trnslp_shfwam_o1
                ADD             R2, R2, R1, LSL#3
                TrnsAsmReg      R2, trnslp_shfwam_size
                ASSERT trnslp_shfwam_size = 2*4

                CMP             R1, #5
                LDREQ           R2, trnslp_shfwam_o24_2
                STREQ           R2, [R10], #4      ; need three insts for 32bpp

;      If putting the sprite (i.e. not plotting the mask)
                TST     R11, #mc_plotmask
Neil Turton's avatar
Neil Turton committed
2039
                BNE     trns_compile_plotmask
Neil Turton's avatar
Neil Turton committed
2040 2041 2042 2043 2044 2045 2046 2047
;      Compile reading of pixel (4,5,5,1 instructions - each input store 5 instructions)
                ADRL            R2, trnslp_readpx_i1
                ADD             R2, R2, R0, LSL#4
                ADD             R2, R2, R0, LSL#2
                TrnsAsmReg      R2, trnslp_readpx_size
                BL              trnslp_chopexcess

                ASSERT trnslp_readpx_size = 5*4
Neil Turton's avatar
Neil Turton committed
2048

Neil Turton's avatar
Neil Turton committed
2049 2050 2051 2052 2053
; if doing 16->32 and 32->16 then build in appropriate munging code
        CMP     R1,#4
        BCC     %FT07
        CMP     R0,#4
        BCC     %FT07
Neil Turton's avatar
Neil Turton committed
2054

Neil Turton's avatar
Neil Turton committed
2055
        CMP     R0,R1
Neil Turton's avatar
Neil Turton committed
2056
        BEQ     %FT07
Neil Turton's avatar
Neil Turton committed
2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074

        ; input and output are both >8bpp and are different
        CMP     R0,#4 ;inbpp
        ADREQ   R2,trnslp_munge_16to321
        TrnsAsmReg R2, trnslp_m1632_size1, EQ
        ADREQ   R2,trnslp_munge_16to322
        TrnsAsmReg R2, trnslp_m1632_size2, EQ
        ADREQ   R2,trnslp_munge_16to323
        TrnsAsmReg R2, trnslp_m1632_size3, EQ
        ADRNE   R2,trnslp_munge_32to161
        TrnsAsmReg R2, trnslp_m3216_size1, NE
        ADRNE   R2,trnslp_munge_32to162
        TrnsAsmReg R2, trnslp_m3216_size2, NE
07

;      If there is a translation table ...
        TST     R11, #mc_ttr
;          then translate the pixel
Neil Turton's avatar
Neil Turton committed
2075
        BEQ     %FT01
Neil Turton's avatar
Neil Turton committed
2076

Neil Turton's avatar
Neil Turton committed
2077
;if inbpp and outbpp are both >8bpp ignore the translation table
Neil Turton's avatar
Neil Turton committed
2078 2079 2080 2081
        CMP     R1,#4
        BCC     %FT09
        CMP     R0,#4
        BCS     %FT08
Neil Turton's avatar
Neil Turton committed
2082
09
Neil Turton's avatar
Neil Turton committed
2083 2084 2085

;if inbpp is 16 or 32 and outbpp is 8 or below we need a CTrans
;32K entry table for colour matched. This will already have been validated
Neil Turton's avatar
Neil Turton committed
2086

Neil Turton's avatar
Neil Turton committed
2087 2088 2089 2090
        CMP     R1,#4
        BCS     %FT07         ;output depth is >8bpp so skip this

        CMP     R0,#4
Neil Turton's avatar
Neil Turton committed
2091
        BCC     %FT07         ;input depth is <16bpp so skip this
Neil Turton's avatar
Neil Turton committed
2092 2093 2094 2095 2096 2097 2098 2099 2100 2101

        ;ok - we definitely need a 32K table here. If it is 32bpp
        ;we also need to munge down to 16bpp before using the table

        ADRNE   R2,trnslp_munge_32to161
        TrnsAsmReg R2, trnslp_m3216_size1, NE
        ADRNE   R2,trnslp_munge_32to162
        TrnsAsmReg R2, trnslp_m3216_size2, NE

        ADRL     R2,trnslp_use32K
Neil Turton's avatar
Neil Turton committed
2102
        TrnsAsmReg R2, trnslp_use32K_size
Neil Turton's avatar
Neil Turton committed
2103 2104
        B       %FT08
07
Neil Turton's avatar
Neil Turton committed
2105 2106 2107

; First check to see if the output depth is greater than 8 bit per pixel,
; if it is then compile in the new translation functions which use
Neil Turton's avatar
Neil Turton committed
2108
; a word array, rather than a byte array!
Neil Turton's avatar
Neil Turton committed
2109 2110

                [ ignore_ttr
Neil Turton's avatar
Neil Turton committed
2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121
                CMP             R1,#4
                BCC             %FT29         ;not if output bpp is <16bpp
                CMP             R0,#4
                BCS             %FT29         ;or input bpp is >8bpp

                LDR             R2,trns_palette
                TEQ             R2,#0
                BEQ             %FT29
                TrnsAsm         trnslp_transpx2, trnslp_transpx2_size

                ;if output is 16bpp now need to munge it down as well
Neil Turton's avatar
Neil Turton committed
2122
                CMP             R1,#5
Neil Turton's avatar
Neil Turton committed
2123 2124 2125 2126 2127 2128
                ADRNE           R2,trnslp_munge_32to161
                TrnsAsmReg      R2, trnslp_m3216_size1, NE
                ADRNE           R2,trnslp_munge_32to162
                TrnsAsmReg      R2, trnslp_m3216_size2, NE
                B               %FT28
29
Neil Turton's avatar
Neil Turton committed
2129
                CMP             R1,#4
Neil Turton's avatar
Neil Turton committed
2130 2131 2132 2133 2134
                TrnsAsm         trnslp_transpx,  trnslp_transpx_size,  LT
                TrnsAsm         trnslp_transpx1, trnslp_transpx1_size, GE
28
                |

Neil Turton's avatar
Neil Turton committed
2135
                CMP             R1,#4
Neil Turton's avatar
Neil Turton committed
2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150
                TrnsAsm         trnslp_transpx,  trnslp_transpx_size,  LT
                TrnsAsm         trnslp_transpx1, trnslp_transpx1_size, GE
                ]
01
08

;      Copy pixel into output pixel word (ORR out_word, out_word, pixel,LSL#32-out_bpp)
                LDR             R2, trnslp_setpx
                MOV             R3, #1
                MOV             R3, R3, LSL R1
                RSB             R3, R3, #32
                SetLsl          R2, R3
                STR             R2, [R10], #4
                ASSERT (trnslp_setpx_size = 4)
;      Assemble mask word
Neil Turton's avatar
Neil Turton committed
2151
trns_compile_plotmask
Neil Turton's avatar
Neil Turton committed
2152 2153 2154 2155
;      If in GCOL 0-7,9,11,13, then assume the mask is whole sprite
        AND     R2, R11, #15            ;       R2 = GCOL in range 0-15
        ADD     R2, R2, #1              ;       R2 = GCOL +1
        MOV     R3, #2_1101010100000000 ;       Bits set are 8, 10, 12, 14, 15
Neil Turton's avatar
Neil Turton committed
2156
        MOVS    R3, R3, LSR R2          ;       Move bit (R2-1) of R3 into the carry flag
Neil Turton's avatar
Neil Turton committed
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
;      CC if GCOL 0-7,9,11,13 (or no mask, in which case GCOL is in range 0-7)

;;-----------------------------------------------------------------------------
;; CC if no mask / CS has a mask so attempt to assemble in the function
;; which is correct for this depth, for 1,2,4 or 8 bit per pixel we can
;; simply compile in the ORR with a suitable mask, for 16 or 24 bit per pixel
;; we need to faff around and generate a new workspace word which
;; contains the correctmask.
;;-----------------------------------------------------------------------------

                BCS             trns_compile_mask

                CMP             R1, #4                          ; is the depth sensible?
                ADRCCL          R2, trnslp_sprnomask_o1
                ADDCC           R2, R2, R1,LSL#2
                TrnsAsmReg      R2, trnslp_sprnomask_size,CC
                ADRCSL          R2, trnslp_sprnomask16or24
                TrnsAsmReg      R2, trnslp_sprnomask16or24_size,CS
                B               trns_compile_nomask

;      Sprite has mask and it is used (GCOL 8,10,12,14,15)

trns_compile_mask

                MOVS            R2, R11, LSR #mcb_sprtype
                BEQ             trns_old_mask

                TrnsAsm         trnslp_new_sprmask, trnslp_new_sprmask_size
                TrnsAsm         trnslp_new_sprmask2, trnslp_new_sprmask2_size
Neil Turton's avatar
Neil Turton committed
2186

Neil Turton's avatar
Neil Turton committed
2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200
                B               trns_any_mask

trns_old_mask
                TrnsAsm         trnslp_sprmask, trnslp_sprmask_size

;      Compile reading of mask pixel (4,5,5,1 instructions - each input store 5 instructions)
                ADRL            R2, trnslp_readpx_i1
                ADD             R2, R2, R0, LSL#4
                ADD             R2, R2, R0, LSL#2
                TrnsAsmReg      R2, trnslp_readpx_size
                BL              trnslp_chopexcess
                ASSERT trnslp_readpx_size = 5*4

                TEQ             R0,R1                   ;Check for 1:1 mapping?
Neil Turton's avatar
Neil Turton committed
2201
                BEQ             trns_compile_mask1to1
Neil Turton's avatar
Neil Turton committed
2202 2203
trns_any_mask
;       Copy mask byte into output mask, first check for non-zero then orr in special case
Neil Turton's avatar
Neil Turton committed
2204

Neil Turton's avatar
Neil Turton committed
2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222
                CMP             R1,#4
                ADRCCL          R2,trnslp_setmask_o1
                ADDCC           R2,R2,R1,LSL #3         ;Each section is 8 bytes (2 words)
                TrnsAsmReg      R2,trnslp_setmask_size,CC
                ASSERT trnslp_setmask_size = 2*4
                ADRCSL          R2,trnslp_setmask16or24
                TrnsAsmReg      R2,trnslp_setmask16or24_size,CS
                B               trns_compile_nomask

;      Copy pixel into output pixel word (ORR out_mask, out_mask, mask_pixel,LSL#32-out_bpp)


trns_compile_mask1to1
                LDR             R2, trnslp_setmask2
                MOV             R3, #1
                MOV             R3, R3, LSL R1
                RSB             R3, R3, #32
                SetLsl          R2, R3
Neil Turton's avatar
Neil Turton committed
2223
                STR             R2, [R10], #4
Neil Turton's avatar
Neil Turton committed
2224 2225 2226 2227
                ASSERT  (trnslp_setmask2_size = 4)

trns_compile_nomask
;      Compile code to read the screen word
2228 2229 2230 2231 2232 2233 2234
 [ AvoidScreenReads
;      If action code 0 (solid), use alternate code that avoids a load if the
;      mask is solid.
                ANDS            R2, R11, #7
                TrnsAsm         trnslp_readscrn0, trnslp_readscrn0_size, EQ
                TrnsAsm         trnslp_readscrn,  trnslp_readscrn_size,  NE
 |
Neil Turton's avatar
Neil Turton committed
2235
                TrnsAsm         trnslp_readscrn, trnslp_readscrn_size
2236
 ]
Neil Turton's avatar
Neil Turton committed
2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248
;      Test for plotting mask - if so compile ECF code, else GCOL code
        TST     R11, #mc_plotmask
        BNE     trns_compile_ecf_store
;      Store the GCOL action code (2,1,2,1,1,0,1,2 instructions, stored as 2 instructions in input)
                ADRL            R3, trnslp_gcol
                ANDS            R2, R11, #7
                ADD             R3, R3, R2,LSL#3
                TrnsAsmReg      R3, trnslp_gcol_size
                CMPNE           R2, #2
                CMPNE           R2, #7
                SUBNE           R10, R10, #4
                CMP             R2, #5
Neil Turton's avatar
Neil Turton committed
2249
                SUBEQ           R10, R10, #4
Neil Turton's avatar
Neil Turton committed
2250 2251 2252 2253 2254
                ASSERT trnslp_gcol_size = 2*4
        B       trns_compiled_gcol
;      Handle the mask and ECF
trns_compile_ecf_store
                TrnsAsm         trnslp_plotmask, trnslp_plotmask_size
Neil Turton's avatar
Neil Turton committed
2255
;      Store the end of loop code
Neil Turton's avatar
Neil Turton committed
2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268
trns_compiled_gcol
                TrnsAsm         trnslp_eoloop, trnslp_eoloop_size
                Pull            "R2"
                TrnsBranch      R2, BGE
;       Store the code for storing the last word
                TrnsAsm         trnslp_lastword, trnslp_lastword_size
; loop
                Push            "R10"
;      Shift pixel and mask words by output bpp (2 instructions)
                ADRL             R2, trnslp_shfwam_o1
                ADD             R2, R2, R1, LSL#3
                TrnsAsmReg      R2, trnslp_shfwam_size
                ASSERT trnslp_shfwam_size = 2*4
Neil Turton's avatar
Neil Turton committed
2269
;      Loop until words are aligned
Neil Turton's avatar
Neil Turton committed
2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285
                Pull            "R2"
                TrnsBranch      R2, BCC
;      Compile code to read the screen word
                TrnsAsm         trnslp_readscrn, trnslp_readscrn_size
;      Test for plotting mask - if so compile ECF code, else GCOL code
        TST     R11, #mc_plotmask
        BNE     trns_compile_ecf_store2
;      Store the GCOL action code (2,1,2,1,1,0,1,2 instructions, stored as 2 instructions in input)
                ADRL            R3, trnslp_gcol
                ANDS            R2, R11, #7
                ADD             R3, R3, R2,LSL#3
                TrnsAsmReg      R3, trnslp_gcol_size
                CMPNE           R2, #2
                CMPNE           R2, #7
                SUBNE           R10, R10, #4
                CMP             R2, #5
Neil Turton's avatar
Neil Turton committed
2286
                SUBEQ           R10, R10, #4
Neil Turton's avatar
Neil Turton committed
2287 2288 2289 2290 2291 2292 2293 2294 2295 2296
                ASSERT trnslp_gcol_size = 2*4
        B       trns_compiled_gcol2
;      Handle the mask and ECF
trns_compile_ecf_store2
                TrnsAsm         trnslp_plotmask, trnslp_plotmask_size
;      Compile code to store the word and exit
trns_compiled_gcol2
                TrnsAsm         trnslp_lastword2, trnslp_lastword2_size
;      Code compiled.
        Debug   mc,"Transformation code ends at",r10
Neil Turton's avatar
Neil Turton committed
2297 2298 2299 2300 2301 2302 2303
	Push	"r0-r2"
	MOV	r2, r10
	LDR	r1, trns_codebuffer
	MOV	r0, #1
	SWI	XOS_SynchroniseCodeAreas
	Pull	"r0-r2"

Neil Turton's avatar
Neil Turton committed
2304 2305 2306 2307 2308
trns_compiling_complete
        Pull    "PC"

trnslp_chopexcess
;this routine reduces the various readpx_i segments down to the real
Neil Turton's avatar
Neil Turton committed
2309
;size rather than five words
Neil Turton's avatar
Neil Turton committed
2310 2311 2312
        TEQ             R0, #0
        SUBEQ           R10, R10, #4
        TEQ             R0, #3
Neil Turton's avatar
Neil Turton committed
2313
        SUBEQ           R10, R10, #16
Neil Turton's avatar
Neil Turton committed
2314 2315 2316
        TEQ             R0, #4
        SUBEQ           R10, R10, #4
        TEQ             R0, #5
Neil Turton's avatar
Neil Turton committed
2317
        SUBEQ           R10, R10, #16
Neil Turton's avatar
Neil Turton committed
2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332
        MOV R15,LR


calc_row_stacked        *       4*4    ;       Number of bytes stacked in plot_and_calculate_row
plot_and_calculate_row
        Push    "R14"
        CMP     trns_scr_lx, trns_scr_rx
        Swap    trns_scr_lx, trns_scr_rx, GT
        LDR     trns_dummy14, gwx0
        CMP     trns_scr_lx, trns_dummy14
        MOVLT   trns_scr_lx, trns_dummy14
        LDR     trns_dummy14, gwx1
        CMP     trns_scr_rx, trns_dummy14
        MOVGT   trns_scr_rx, trns_dummy14
        CMP     trns_scr_lx, trns_scr_rx
2333
        Pull    "PC",GE
Neil Turton's avatar
Neil Turton committed
2334 2335
;                                       Get sprite offsets for left of current y line
;                                       First get dummy11 = scr_lx - x(0)
Neil Turton's avatar
Neil Turton committed
2336
        LDR     trns_dummy11, trns_spr_xcoords + calc_row_stacked
Neil Turton's avatar
Neil Turton committed
2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356
;        Debug tr,"X,Y(x0,y0), incXx, incYy",trns_X_x0_y,trns_Y_x0_y,trns_inc_X_x,trns_inc_Y_x
;        Debug tr,"coords:",trns_scr_lx, trns_scr_rx,trns_scr_y,trns_dummy11
        MOV     trns_dummy11, trns_dummy11, ASR#8
        SUB     trns_dummy11, trns_scr_lx, trns_dummy11
; X = ((screen_lx%-x(0)) * (inc_X_x)) + X_x0_y
        MLA     trns_X, trns_dummy11, trns_inc_X_x, trns_X_x0_y
; Y = ((screen_lx%-x(0)) * (spr_inc_Y_x)) + Y_x0_y
        MLA     trns_Y, trns_inc_Y_x, trns_dummy11, trns_Y_x0_y
;                                       Get the x posn and x size for the plot
        SUB     trns_dummy14, trns_scr_rx, trns_scr_lx
        MOV     trns_out_x, trns_scr_lx
;                                       Load the compile routine registers - HERE
        ADR     trns_spr_start, trns_comp_spr_left + calc_row_stacked
        LDMIA   trns_spr_start, {trns_xsize, trns_spr_start, trns_byte_width, trns_spr_height}
        ORR     trns_xsize, trns_xsize, trns_dummy14,LSL#16
;                               Plot the row (call compiled code)
        Pull    "R14"
        LDR     PC, trns_codebuffer + calc_row_stacked -4

        END