overdraw eliminated in AS mode
[picodrive.git] / Pico / Draw.s
index 3a3da81..c620c74 100644 (file)
@@ -1,9 +1,9 @@
 @ vim:filetype=armasm\r
 \r
-@ assembly "optimized" version of some funtions from draw.c\r
+@ ARM assembly versions of some funtions from draw.c\r
 @ this is highly specialized, be careful if changing related C code!\r
 \r
-@ (c) Copyright 2007, Grazvydas "notaz" Ignotas\r
+@ (c) Copyright 2007-2008, Grazvydas "notaz" Ignotas\r
 @ All Rights Reserved\r
 \r
 .include "port_config.s"\r
 .extern Pico\r
 .extern PicoOpt\r
 .extern HighCol\r
-.extern Scanline\r
+.extern DrawScanline\r
 .extern HighSprZ\r
 .extern rendstatus\r
+.extern HighPreSpr\r
 .extern DrawLineDest\r
 .extern DrawStripInterlace\r
+.extern HighCacheS_ptr\r
 \r
+.equ PDRAW_SPRITES_MOVED, (1<<0)\r
+.equ PDRAW_WND_DIFF_PRIO, (1<<1)\r
+.equ PDRAW_ACC_SPRITES,   (1<<2)\r
+.equ PDRAW_DIRTY_SPRITES, (1<<4)\r
+.equ PDRAW_PLANE_HI_PRIO, (1<<6)\r
+.equ PDRAW_SHHI_DONE,     (1<<7)\r
+.equ MAX_LINE_SPRITES,    30\r
 \r
 @ helper\r
 .macro TilePixel pat lsrr offs\r
 .endif\r
     ldreqb  r4, [r1,#\offs]\r
     orrne   r4, r3, r4\r
-    strneb  r4, [r1,#\offs]\r
-    tsteq   r4, #0x80\r
     andeq   r4, r4, #0x3f\r
-    streqb  r4, [r1,#\offs]\r
+    strb    r4, [r1,#\offs]\r
 .endm\r
 \r
 @ TileNormShHP (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: register with helper pattern 0xf, touches r3 high bits\r
 .else\r
     ands    r4, r12, r2\r
 .endif\r
-    beq     3f\r
+    beq     0f\r
     cmp     r4, #0xe\r
-    beq     2f\r
-    bgt     1f\r
-    orr     r4, r3, r4\r
-    strb    r4, [r1,#\ofs]\r
-    b       3f\r
-1:\r
-    ldrb    r4, [r1,#\ofs]        @ 2ci\r
-    orr     r4, r4, #0xc0\r
-    strb    r4, [r1,#\ofs]\r
-    b       3f\r
-2:\r
-    ldrb    r4, [r1,#\ofs]        @ 2ci\r
-    bic     r4, r4, #0xc0\r
-    orr     r4, r4, #0x80\r
+    ldrgeb  r4, [r1,#\ofs]\r
+    orrlt   r4, r3, r4            @ normal\r
+\r
+    biceq   r4, r4, #0xc0         @ hilight\r
+    orreq   r4, r4, #0x80\r
+    orrgt   r4, r4, #0xc0         @ shadow\r
+\r
     strb    r4, [r1,#\ofs]\r
-3:\r
+0:\r
 .endm\r
 \r
 @ TileFlipSh (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=sx, r12: register with helper pattern 0xf\r
     TileDoShGenPixel 16,  7 @ #0x000f0000\r
 .endm\r
 \r
+.macro TileDoShGenPixel_noop shift ofs\r
+.if \shift\r
+    and     r4, r12, r2, lsr #\shift\r
+.else\r
+    and     r4, r12, r2\r
+.endif\r
+    sub     r7, r4, #1\r
+    cmp     r7, #0xd\r
+    orrcc   r4, r3, r4           @ 0-0xc (was 1-0xd)\r
+    strccb  r4, [r1,#\ofs]\r
+.endm\r
+\r
+.macro TileFlipSh_noop\r
+    TileDoShGenPixel_noop 16,  0 @ #0x000f0000\r
+    TileDoShGenPixel_noop 20,  1 @ #0x00f00000\r
+    TileDoShGenPixel_noop 24,  2 @ #0x0f000000\r
+    TileDoShGenPixel_noop 28,  3 @ #0xf0000000\r
+    TileDoShGenPixel_noop  0,  4 @ #0x0000000f\r
+    TileDoShGenPixel_noop  4,  5 @ #0x000000f0\r
+    TileDoShGenPixel_noop  8,  6 @ #0x00000f00\r
+    TileDoShGenPixel_noop 12,  7 @ #0x0000f000\r
+.endm\r
+\r
+.macro TileNormSh_noop\r
+    TileDoShGenPixel_noop 12,  0 @ #0x0000f000\r
+    TileDoShGenPixel_noop  8,  1 @ #0x00000f00\r
+    TileDoShGenPixel_noop  4,  2 @ #0x000000f0\r
+    TileDoShGenPixel_noop  0,  3 @ #0x0000000f\r
+    TileDoShGenPixel_noop 28,  4 @ #0xf0000000\r
+    TileDoShGenPixel_noop 24,  5 @ #0x0f000000\r
+    TileDoShGenPixel_noop 20,  6 @ #0x00f00000\r
+    TileDoShGenPixel_noop 16,  7 @ #0x000f0000\r
+.endm\r
+\r
+.macro TileDoShGenPixel_onlyop_lp shift ofs\r
+.if \shift\r
+    ands    r7, r12, r2, lsr #\shift\r
+.else\r
+    ands    r7, r12, r2\r
+.endif\r
+    ldrneb  r4, [r1,#\ofs]\r
+    tstne   r4, #0x40\r
+    beq     0f\r
+\r
+    cmp     r7, #0xe\r
+    biceq   r4, r4, #0xc0         @ hilight\r
+    orreq   r4, r4, #0x80\r
+    orrgt   r4, r4, #0xc0         @ shadow\r
+    strgeb  r4, [r1,#\ofs]\r
+0:\r
+.endm\r
+\r
+.macro TileFlipSh_onlyop_lp\r
+    TileDoShGenPixel_onlyop_lp 16,  0 @ #0x000f0000\r
+    TileDoShGenPixel_onlyop_lp 20,  1 @ #0x00f00000\r
+    TileDoShGenPixel_onlyop_lp 24,  2 @ #0x0f000000\r
+    TileDoShGenPixel_onlyop_lp 28,  3 @ #0xf0000000\r
+    TileDoShGenPixel_onlyop_lp  0,  4 @ #0x0000000f\r
+    TileDoShGenPixel_onlyop_lp  4,  5 @ #0x000000f0\r
+    TileDoShGenPixel_onlyop_lp  8,  6 @ #0x00000f00\r
+    TileDoShGenPixel_onlyop_lp 12,  7 @ #0x0000f000\r
+.endm\r
+\r
+.macro TileNormSh_onlyop_lp\r
+    TileDoShGenPixel_onlyop_lp 12,  0 @ #0x0000f000\r
+    TileDoShGenPixel_onlyop_lp  8,  1 @ #0x00000f00\r
+    TileDoShGenPixel_onlyop_lp  4,  2 @ #0x000000f0\r
+    TileDoShGenPixel_onlyop_lp  0,  3 @ #0x0000000f\r
+    TileDoShGenPixel_onlyop_lp 28,  4 @ #0xf0000000\r
+    TileDoShGenPixel_onlyop_lp 24,  5 @ #0x0f000000\r
+    TileDoShGenPixel_onlyop_lp 20,  6 @ #0x00f00000\r
+    TileDoShGenPixel_onlyop_lp 16,  7 @ #0x000f0000\r
+.endm\r
+\r
 \r
 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
 \r
@@ -250,7 +324,7 @@ DrawLayer:
     ldreqb  r12, [r11, #2]\r
     ldrneb  r12, [r11, #4]\r
 \r
-    ldr     r2, =Scanline         @ trying to make good use of pipeline here\r
+    ldr     r2, =DrawScanline     @ trying to make good use of pipeline here\r
     ldr     lr, =(Pico+0x10000)   @ lr=Pico.vram\r
 \r
     moveq   r12, r12, lsl #10\r
@@ -264,7 +338,7 @@ DrawLayer:
     mov     r4, r8, lsr #8        @ pvid->reg[13]\r
     mov     r4, r4, lsl #10       @ htab=pvid->reg[13]<<9; (halfwords)\r
     tst     r7, #2\r
-    addne   r4, r4, r2, lsl #2    @ htab+=Scanline<<1; // Offset by line\r
+    addne   r4, r4, r2, lsl #2    @ htab+=DrawScanline<<1; // Offset by line\r
     tst     r7, #1\r
     biceq   r4, r4, #0x1f         @ htab&=~0xf; // Offset by tile\r
     add     r4, r4, r0, lsl #1    @ htab+=plane\r
@@ -433,7 +507,7 @@ DrawLayer:
     mov     r0, #0\r
     ldreq   r2, [r1]\r
     str     r0, [r6]    @ terminate the cache list\r
-    orreq   r2, r2, #0x40 @ had a layer with all hi-prio tiles\r
+    orreq   r2, r2, #PDRAW_PLANE_HI_PRIO @ had a layer with all hi-prio tiles\r
     streq   r2, [r1]\r
 \r
     ldmfd   sp!, {r4-r11,lr}\r
@@ -444,10 +518,10 @@ DrawLayer:
 .DrawStrip_vsscroll:\r
     rsb     r8, r3, #0\r
     mov     r8, r8, lsr #3        @ r8=tilex=(-ts->hscroll)>>3\r
-    bic     r8, r8, #0xff000000\r
-    orr     r8, r8, r5, lsl #25   @ r8=(xmask[31:25]|had_output[24]|tilex[23:0])\r
+    bic     r8, r8, #0x3fc00000\r
+    orr     r8, r8, r5, lsl #25   @ r8=(xmask[31:25]|had_output[24]|tilex[21:0])\r
 \r
-    ldr     r4, =Scanline\r
+    ldr     r4, =DrawScanline\r
     orr     r5, r1, r10, lsl #24\r
     ldr     r4, [r4]\r
     sub     r1, r3, #1\r
@@ -504,9 +578,9 @@ DrawLayer:
     ldrh    r7, [r7]              @ r7=vscroll\r
 \r
     bic     r10,r10,#0xff         @ clear old ty\r
-    and     r4, r5, #0xff0000\r
-    add     r4, r4, r7, lsl #16\r
-    and     r4, r4, r5, lsl #16   @ r4=line<<16\r
+    and     r4, r5, #0xff0000     @ scanline\r
+    add     r4, r4, r7, lsl #16   @ ... += vscroll\r
+    and     r4, r4, r5, lsl #16   @ ... &= ymask\r
     and     r7, r4, #0x70000\r
     orr     r10,r10,r7, lsr #15   @ new ty\r
 \r
@@ -529,7 +603,7 @@ DrawLayer:
     beq     .DrawStrip_vs_samecode @ we know stuff about this tile already\r
 \r
     mov     r9, r7          @ remember code\r
-    orr     r8, r8, #1<<24  @ seen non hi-prio tile\r
+    orr     r8, r8, #(1<<24)@ seen non hi-prio tile\r
 \r
     movs    r2, r9, lsl #20 @ if (code&0x1000)\r
     mov     r2, r2, lsl #1\r
@@ -603,12 +677,12 @@ DrawLayer:
     b       .dsloop_vs\r
 \r
 .dsloop_vs_exit:\r
-    tst     r8, #1<<24 @ seen non hi-prio tile\r
+    tst     r8, #(1<<24) @ seen non hi-prio tile\r
     ldreq   r1, =rendstatus\r
     mov     r0, #0\r
     ldreq   r2, [r1]\r
     str     r0, [r6]    @ terminate the cache list\r
-    orreq   r2, r2, #0x40 @ had a layer with all hi-prio tiles\r
+    orreq   r2, r2, #PDRAW_PLANE_HI_PRIO @ had a layer with all hi-prio tiles\r
     streq   r2, [r1]\r
 \r
     ldmfd   sp!, {r4-r11,lr}\r
@@ -624,7 +698,7 @@ DrawLayer:
     movne   r7, r7, lsl #5\r
 \r
     @ Find the line in the name table\r
-    add     r2, r7, r2, lsl #22    @ r2=(vscroll+(Scanline<<1))<<21 (11 bits);\r
+    add     r2, r7, r2, lsl #22    @ r2=(vscroll+(DrawScanline<<1))<<21 (11 bits);\r
     orr     r1, r1, #0x80000000\r
     and     r2, r2, r1, ror #10    @ &((ymask<<1)|1)<<21;\r
     mov     r2, r2, lsr #21\r
@@ -798,39 +872,25 @@ DrawTilesFromCache:
     b       .dtfc_loop\r
 \r
 .dtfc_shadow_blank:\r
-    ldrb    r4, [r1]        @ 1ci\r
-    ldrb    r12,[r1,#1]\r
-    tst     r4, #0x80\r
-    andeq   r4, r4,#0x3f\r
-    streqb  r4, [r1]\r
-    tst     r12,#0x80\r
-    ldrb    r4, [r1,#2]\r
-    andeq   r12,r12,#0x3f\r
-    streqb  r12,[r1,#1]\r
-    tst     r4, #0x80\r
-    ldrb    r12,[r1,#3]\r
-    andeq   r4, r4,#0x3f\r
-    streqb  r4, [r1,#2]\r
-    tst     r12,#0x80\r
-    ldrb    r4, [r1,#4]\r
-    andeq   r12,r12,#0x3f\r
-    streqb  r12,[r1,#3]\r
-    tst     r4, #0x80\r
-    ldrb    r12,[r1,#5]\r
-    andeq   r4, r4,#0x3f\r
-    streqb  r4, [r1,#4]\r
-    tst     r12,#0x80\r
-    ldrb    r4, [r1,#6]\r
-    andeq   r12,r12,#0x3f\r
-    streqb  r12,[r1,#5]\r
-    tst     r4, #0x80\r
-    ldrb    r12,[r1,#7]\r
-    andeq   r4, r4,#0x3f\r
-    streqb  r4, [r1,#6]\r
-    tst     r12,#0x80\r
-    andeq   r12,r12,#0x3f\r
-    streqb  r12,[r1,#7]\r
-    mov     r12, #0xf\r
+    tst     r1, #1\r
+    ldrneb  r4, [r1]\r
+    mov     r6, #0x3f\r
+    and     r4, r4, #0x3f\r
+    strneb  r4, [r1], #1\r
+    ldrh    r4, [r1]\r
+    orr     r6, r6, r6, lsl #8\r
+    and     r4, r4, r6\r
+    strh    r4, [r1], #2\r
+    ldrh    r4, [r1]\r
+    and     r4, r4, r6\r
+    strh    r4, [r1], #2\r
+    ldrh    r4, [r1]\r
+    and     r4, r4, r6\r
+    strh    r4, [r1], #2\r
+    ldrh    r4, [r1]\r
+    and     r4, r4, r6\r
+    streqh  r4, [r1]\r
+    strneb  r4, [r1]\r
     b       .dtfc_loop\r
 \r
 .dtfc_cut_tile:\r
@@ -856,52 +916,57 @@ DrawTilesFromCache:
 .dtfc_check_rendflags:\r
     ldr     r1, =rendstatus\r
     ldr     r2, [r1]\r
-    tst     r2, #0xc0\r
+    tst     r2, #(PDRAW_PLANE_HI_PRIO|PDRAW_SHHI_DONE)\r
     beq     .dtfc_loop\r
     bic     r8, r8, #1      @ sh/hi mode off\r
-    tst     r2, #0x80\r
+    tst     r2, #PDRAW_SHHI_DONE\r
     bne     .dtfc_loop      @ already processed\r
-    orr     r2, r2, #0x80\r
+    orr     r2, r2, #PDRAW_SHHI_DONE\r
     str     r2, [r1]\r
 \r
     add     r1, r11,#8\r
-    mov     r3, #320/4\r
-    mov     r7, #0x80\r
-    orr     r7, r7, r7, lsl #8\r
-    orr     r7, r7, r7, lsl #16\r
+    mov     r3, #320/4/4\r
     mov     r6, #0x3f\r
     orr     r6, r6, r6, lsl #8\r
     orr     r6, r6, r6, lsl #16\r
 .dtfc_loop_shprep:\r
+    ldmia   r1, {r2,r4,r5,r7}\r
     subs    r3, r3, #1\r
-    bmi     .dtfc_loop      @ done\r
-    ldr     r2, [r1]\r
-    tst     r2, r7\r
-    andeq   r2, r2, r6\r
-    streq   r2, [r1], #4\r
-    beq     .dtfc_loop_shprep\r
-    tst     r2,     #0x80000000\r
-    biceq   r2, r2, #0xc0000000\r
-    tst     r2,     #0x00800000\r
-    biceq   r2, r2, #0x00c00000\r
-    tst     r2,     #0x00008000\r
-    biceq   r2, r2, #0x0000c000\r
-    tst     r2,     #0x00000080\r
-    biceq   r2, r2, #0x000000c0\r
-    str     r2, [r1], #4\r
-    b       .dtfc_loop_shprep\r
+    and     r2, r2, r6\r
+    and     r4, r4, r6\r
+    and     r5, r5, r6\r
+    and     r7, r7, r6\r
+    stmia   r1!,{r2,r4,r5,r7}\r
+    bne     .dtfc_loop_shprep\r
+\r
+    mvn     r5, #0         @ r5=prevcode=-1\r
+    b       .dtfc_loop\r
 \r
 .pool\r
 \r
 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
 \r
 \r
-.global DrawSpritesFromCache @ int *hc, int sh\r
+.global DrawSpritesSHi @ int prio_unused, int sh\r
+\r
+DrawSpritesSHi:\r
+    ldr     r3, =DrawScanline\r
+    ldr     r2, =HighLnSpr\r
+    ldr     r12,[r3]\r
+    mov     r3, #(MAX_LINE_SPRITES+2)\r
+    mla     r2, r12, r3, r2\r
+    ldr     r3, [r2]\r
+    ands    r3, r3, #0x7f\r
+    bxeq    lr\r
 \r
-DrawSpritesFromCache:\r
     stmfd   sp!, {r4-r11,lr}\r
+    mov     r12,#0xff\r
+    strb    r12,[r2,#1]     @ set end marker\r
+    add     r10,r2, #2\r
+    add     r10,r10,r3      @ r10=HighLnSpr end\r
+\r
+    str     r1, [sp, #-4]   @ no calls after this point\r
 \r
-    @ cache some stuff to avoid mem access\r
 .if OVERRIDE_HIGHCOL\r
     ldr     r11,=HighCol\r
     mov     r12,#0xf\r
@@ -911,134 +976,231 @@ DrawSpritesFromCache:
     mov     r12,#0xf\r
 .endif\r
     ldr     lr, =(Pico+0x10000) @ lr=Pico.vram\r
-    mov     r6, r1, lsl #31\r
-    orr     r6, r6, #1<<30\r
 \r
-    mov     r10, r0\r
 \r
-.dsfc_loop:\r
-    ldr     r9, [r10], #4    @ read code\r
-    bic     r6, r6, #7       @ using pipeline\r
-    tst     r9, r9\r
-    ldmeqfd sp!, {r4-r11,pc}\r
+DrawSpriteSHi:\r
+    @ draw next sprite\r
+    ldrb    r0, [r10,#-1]!\r
+    ldr     r1, =HighPreSpr\r
+    ldr     r8, [sp, #-4]\r
+    cmp     r0, #0xff\r
+    ldmeqfd sp!, {r4-r11,pc} @ end of list\r
+    and     r0, r0, #0x7f\r
+    add     r0, r1, r0, lsl #3\r
 \r
-    mov     r4, r9, lsl #28\r
-    orr     r6, r6, r4, lsr #30\r
-    add     r6, r6, #1       @ r6=s1cc???? ... ?????www (s=shadow/hilight, cc=pal, w=width)\r
+    ldr     r9, [r0, #4]    @ sprite[1]\r
+    mov     r2, r9, asr #16 @ r2=sx\r
 \r
-    and     r5, r9, #3\r
-    add     r5, r5, #1       @ r5=delta\r
-    tst     r9, #0x10000\r
-    rsbne   r5, r5, #0       @ Flip X\r
-    mov     r5, r5, lsl #4\r
+    mov     r9, r9, lsl #16\r
+    mov     r3, r9, lsr #31 @ priority\r
+    mov     r9, r9, lsr #16\r
+    orr     r9, r9, r8, lsl #31 @ r9=code|sh[31]\r
+    and     r4, r9, #0x6000\r
+    orr     r9, r9, r4, lsl #16\r
+    orr     r9, r9, #0x10000000 @ r9=scc1 ???? ... <code> (s=shadow/hilight, cc=pal)\r
+    cmp     r12,r9, lsr #28 @ sh/hi with pal3?\r
+    cmpne   r3, #1          @ if not, is hi prio\r
+    bne     DrawSpriteSHi   @ non-operator low sprite, already drawn\r
 \r
-    mov     r2, r9, lsr #17\r
-    mov     r8, r2, lsl #1   @ tile=((unsigned int)code>>17)<<1;\r
+    ldr     r3, [r0]        @ sprite[0]\r
+    ldr     r7, =DrawScanline\r
+    mov     r6, r3, lsr #28\r
+    sub     r6, r6, #1      @ r6=width-1 (inc later)\r
+    mov     r5, r3, lsr #24\r
+    and     r5, r5, #7      @ r5=height\r
 \r
-    and     r3, r9, #0x30    @ r3=pal=(code&0x30);\r
+    mov     r0, r3, lsl #16 @ r4=sy<<16 (tmp)\r
 \r
-    bic     r6, r6, #3<<28\r
-    orr     r6, r6, r3, lsl #24\r
+    ldr     r7, [r7]\r
+    sub     r7, r7, r0, asr #16 @ r7=row=DrawScanline-sy\r
 \r
-    mov     r0, r9, lsl #16\r
-    mov     r0, r0, asr #22  @ sx=(code<<16)>>22\r
-    adds    r0, r0, #0       @ set ZV\r
-    b       .dsfc_inloop_enter\r
+    tst     r9, #0x1000\r
+    movne   r0, r5, lsl #3\r
+    subne   r0, r0, #1\r
+    subne   r7, r0, r7      @ if (code&0x1000) row=(height<<3)-1-row; // Flip Y\r
 \r
-@ scratch: r4, r7\r
-.dsfc_inloop:\r
-    sub     r6, r6, #1\r
-    tst     r6, #7\r
-    beq     .dsfc_loop\r
-    adds    r0, r0, #8\r
-    add     r8, r8, r5\r
-\r
-.dsfc_inloop_enter:\r
-    ble     .dsfc_inloop\r
+    add     r8, r9, r7, lsr #3 @ tile+=row>>3; // Tile number increases going down\r
+    tst     r9, #0x0800\r
+    mlane   r8, r5, r6, r8  @ if (code&0x0800) { tile+=delta*(width-1);\r
+    rsbne   r5, r5, #0      @ delta=-delta; } // r5=delta now\r
+\r
+    mov     r8, r8, lsl #21\r
+    mov     r8, r8, lsr #17\r
+    and     r7, r7, #7\r
+    add     r8, r8, r7, lsl #1 @ tile+=(row&7)<<1; // Tile address\r
+\r
+    mov     r5, r5, lsl #4     @ delta<<=4; // Delta of address\r
+\r
+    orrs    r3, r9, r9, lsl #4\r
+    mov     r3, r4, lsr #9     @ r3=pal=((code>>9)&0x30);\r
+\r
+    add     r6, r6, #1         @ inc now\r
+    adds    r0, r2, #0         @ mov sx to r0 and set ZV flags\r
+    b       .dsprShi_loop_enter\r
+\r
+.dsprShi_loop:\r
+    subs    r6, r6, #1         @ width--\r
+    beq     DrawSpriteSHi\r
+    adds    r0, r0, #8         @ sx+=8\r
+    add     r8, r8, r5         @ tile+=delta\r
+\r
+.dsprShi_loop_enter:\r
+    ble     .dsprShi_loop     @ sx <= 0\r
     cmp     r0, #328\r
-    bge     .dsfc_loop\r
+    bge     DrawSpriteSHi\r
 \r
     mov     r8, r8, lsl #17\r
-    mov     r8, r8, lsr #17   @ tile&=0x7fff; // Clip tile address\r
+    mov     r8, r8, lsr #17    @ tile&=0x7fff; // Clip tile address\r
 \r
-    ldr     r2, [lr, r8, lsl #1] @ pack=*(unsigned int *)(Pico.vram+tile); // Get 8 pixels\r
-    add     r1, r11, r0       @ r1=pdest\r
+    ldr     r2, [lr, r8, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
+    add     r1, r11, r0        @ r1=pdest\r
     tst     r2, r2\r
-    beq     .dsfc_inloop\r
+    beq     .dsprShi_loop\r
 \r
-    cmp     r12, r6, lsr #28\r
-    beq     .dsfc_shadow\r
+    cmp     r12, r9, lsr #28\r
+    beq     .dsprShi_shadow\r
 \r
     cmp     r2, r2, ror #4\r
-    beq     .dsfc_SingleColor @ tileline singlecolor \r
+    beq     .dsprShi_SingleColor @ tileline singlecolor \r
 \r
-    tst     r9, #0x10000\r
-    bne     .dsfc_TileFlip\r
+    tst     r9, #0x0800\r
+    bne     .dsprShi_TileFlip\r
 \r
-    @ TileFlip (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
-.dsfc_TileNorm:\r
+    @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
+@ scratch: r4, r7\r
+.dsprShi_TileNorm:\r
     TileNorm r12\r
-    b       .dsfc_inloop\r
+    b       .dsprShi_loop\r
 \r
-.dsfc_TileFlip:\r
+.dsprShi_TileFlip:\r
     TileFlip r12\r
-    b       .dsfc_inloop\r
+    b       .dsprShi_loop\r
 \r
-.dsfc_SingleColor:\r
-    tst     r0, #1              @ not aligned?\r
+.dsprShi_SingleColor:\r
     and     r4, r2, #0xf\r
     orr     r4, r3, r4\r
     orr     r4, r4, r4, lsl #8\r
+    tst     r0, #1              @ not aligned?\r
     strneb  r4, [r1], #1\r
     streqh  r4, [r1], #2\r
     strh    r4, [r1], #2\r
     strh    r4, [r1], #2\r
     strh    r4, [r1], #2\r
     strneb  r4, [r1], #1\r
-    b       .dsfc_inloop\r
+    b       .dsprShi_loop\r
+\r
+.dsprShi_shadow:\r
+    tst     r9, #0x8000\r
+    beq     .dsprShi_shadow_lowpri\r
 \r
-.dsfc_shadow:\r
     cmp     r2, r2, ror #4\r
-    beq     .dsfc_singlec_sh\r
+    beq     .dsprShi_singlec_sh\r
 \r
-    tst     r9, #0x10000\r
-    bne     .dsfc_TileFlip_sh\r
+    tst     r9, #0x0800\r
+    bne     .dsprShi_TileFlip_sh\r
 \r
     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
-.dsfc_TileNorm_sh:\r
+.dsprShi_TileNorm_sh:\r
     TileNormSh\r
-    b       .dsfc_inloop\r
+    b       .dsprShi_loop\r
 \r
-.dsfc_TileFlip_sh:\r
+.dsprShi_TileFlip_sh:\r
     TileFlipSh\r
-    b       .dsfc_inloop\r
+    b       .dsprShi_loop\r
 \r
-.dsfc_singlec_sh:\r
+.dsprShi_singlec_sh:\r
     cmp     r2, #0xe0000000\r
-    bcc     .dsfc_SingleColor   @ normal singlecolor tileline (carry inverted in ARM)\r
+    bcc     .dsprShi_SingleColor   @ normal singlecolor tileline (carry inverted in ARM)\r
     tst     r2, #0x10000000\r
-    bne     .dsfc_sh_sh\r
+    bne     .dsprShi_sh_sh\r
     TileSingleHi\r
-    b       .dsfc_inloop\r
+    b       .dsprShi_loop\r
 \r
-.dsfc_sh_sh:\r
+.dsprShi_sh_sh:\r
     TileSingleSh\r
-    b       .dsfc_inloop\r
+    b       .dsprShi_loop\r
+\r
+.dsprShi_shadow_lowpri:\r
+    tst     r9, #0x800\r
+    bne     .dsprShi_TileFlip_sh_lp\r
+\r
+.dsprShi_TileNorm_sh_lp:\r
+    TileNormSh_onlyop_lp\r
+    b       .dsprShi_loop\r
+\r
+.dsprShi_TileFlip_sh_lp:\r
+    TileFlipSh_onlyop_lp\r
+    b       .dsprShi_loop\r
 \r
 .pool\r
 \r
 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
 \r
-@ + 0  :    hhhhvvvv ab--hhvv yyyyyyyy yyyyyyyy // a: offscreen h, b: offs. v, h: horiz. size\r
-@ + 4  :    xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8\r
+.global DrawAllSprites @ int prio, int sh\r
+\r
+DrawAllSprites:\r
+    ldr     r3, =rendstatus\r
+    orr     r1, r1, r0, lsl #1\r
+    ldr     r12,[r3]\r
+    tst     r12,#(PDRAW_ACC_SPRITES|PDRAW_SPRITES_MOVED)\r
+    beq     das_no_prep\r
+    stmfd   sp!, {r1,lr}\r
+    and     r0, r12,#PDRAW_DIRTY_SPRITES\r
+    bic     r12,r12,#(PDRAW_ACC_SPRITES|PDRAW_SPRITES_MOVED)\r
+    str     r12,[r3]\r
+    bl      PrepareSprites\r
+    ldmfd   sp!, {r1,lr}\r
+\r
+das_no_prep:\r
+    ldr     r3, =DrawScanline\r
+    ldr     r2, =HighLnSpr\r
+    ldr     r12,[r3]\r
+    mov     r3, #(MAX_LINE_SPRITES+2)\r
+    mla     r2, r12, r3, r2\r
+    ldr     r3, [r2]\r
+    ands    r3, r3, #0x7f\r
+    bxeq    lr\r
+\r
+    @ time to do some real work\r
+    stmfd   sp!, {r4-r11,lr}\r
+    mov     r12,#0xff\r
+    strb    r12,[r2,#1]     @ set end marker\r
+    add     r10,r2, #2\r
+    add     r10,r10,r3      @ r10=HighLnSpr end\r
 \r
-.global DrawSprite @ unsigned int *sprite, int **hc, int sh\r
+    str     r1, [sp, #-4]   @ no calls after this point\r
 \r
-DrawSprite:\r
-    stmfd   sp!, {r4-r9,r11,lr}\r
+.if OVERRIDE_HIGHCOL\r
+    ldr     r11,=HighCol\r
+    mov     r12,#0xf\r
+    ldr     r11,[r11]\r
+.else\r
+    ldr     r11,=HighCol\r
+    mov     r12,#0xf\r
+.endif\r
+    ldr     lr, =(Pico+0x10000) @ lr=Pico.vram\r
+\r
+@ + 0  :    hhhhvvvv ----hhvv yyyyyyyy yyyyyyyy // v, h: horiz. size\r
+@ + 4  :    xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8\r
+\r
+DrawSprite: @ was: unsigned int *sprite, int sh, int acc_sprites\r
+    @ draw next sprite\r
+    ldrb    r0, [r10,#-1]!\r
+    ldr     r1, =HighPreSpr\r
+    ldr     r8, [sp, #-4]\r
+    mov     r2, r0, lsr #7\r
+    cmp     r0, #0xff\r
+    ldmeqfd sp!, {r4-r11,pc} @ end of list\r
+    cmp     r2, r8, lsr #1\r
+    bne     DrawSprite      @ wrong priority\r
+    and     r0, r0, #0x7f\r
+    add     r0, r1, r0, lsl #3\r
+\r
+@    stmfd   sp!, {r4-r9,r11,lr}\r
+@    orr     r8, r2, r1, lsl #4\r
 \r
     ldr     r3, [r0]        @ sprite[0]\r
-    ldr     r7, =Scanline\r
+    ldr     r7, =DrawScanline\r
     mov     r6, r3, lsr #28\r
     sub     r6, r6, #1      @ r6=width-1 (inc later)\r
     mov     r5, r3, lsr #24\r
@@ -1048,52 +1210,37 @@ DrawSprite:
 \r
     ldr     r7, [r7]\r
     ldr     r9, [r0, #4]\r
-    sub     r7, r7, r4, asr #16 @ r7=row=Scanline-sy\r
+    sub     r7, r7, r4, asr #16 @ r7=row=DrawScanline-sy\r
 \r
-    tst     r2, r2\r
     mov     r2, r9, asr #16 @ r2=sx\r
-    bic     r9, r9, #0xfe000000\r
-    orrne   r9, r9, #1<<31  @ r9=code|(sh<<31)\r
+    mov     r9, r9, lsl #16\r
+    mov     r9, r9, lsr #16\r
+    orr     r9, r9, r8, lsl #31 @ r9=code|sh[31]\r
 \r
     tst     r9, #0x1000\r
     movne   r4, r5, lsl #3\r
     subne   r4, r4, #1\r
     subne   r7, r4, r7      @ if (code&0x1000) row=(height<<3)-1-row; // Flip Y\r
 \r
-    mov     r8, r9, lsl #21\r
-    mov     r8, r8, lsr #21\r
-    add     r8, r8, r7, lsr #3 @ tile+=row>>3; // Tile number increases going down\r
-    \r
+    add     r8, r9, r7, lsr #3 @ tile+=row>>3; // Tile number increases going down\r
     tst     r9, #0x0800\r
     mlane   r8, r5, r6, r8  @ if (code&0x0800) { tile+=delta*(width-1);\r
     rsbne   r5, r5, #0      @ delta=-delta; } // r5=delta now\r
 \r
-    mov     r8, r8, lsl #4\r
+    mov     r8, r8, lsl #21\r
+    mov     r8, r8, lsr #17\r
     and     r7, r7, #7\r
     add     r8, r8, r7, lsl #1 @ tile+=(row&7)<<1; // Tile address\r
 \r
-    tst     r9, #0x8000\r
-    bne     .dspr_cache       @ if(code&0x8000) // high priority - cache it\r
-\r
+.dspr_continue:\r
     @ cache some stuff to avoid mem access\r
-.if OVERRIDE_HIGHCOL\r
-    ldr     r11,=HighCol\r
-    mov     r12,#0xf\r
-    ldr     r11,[r11]\r
-.else\r
-    ldr     r11,=HighCol\r
-    mov     r12,#0xf\r
-.endif\r
-    ldr     lr, =(Pico+0x10000) @ lr=Pico.vram\r
-\r
     mov     r5, r5, lsl #4     @ delta<<=4; // Delta of address\r
     and     r4, r9, #0x6000\r
     orr     r9, r9, r4, lsl #16\r
-    orr     r9, r9, #0x10000000 @ r9=scc1 ???? ... <code> (s=shadow/hilight, cc=pal)\r
+    orrs    r9, r9, #0x10000000 @ r9=scc1 ???? ... <code> (s=shadow/hilight, cc=pal)\r
 \r
-    tst     r9, #1<<31\r
     mov     r3, r4, lsr #9     @ r3=pal=((code>>9)&0x30);\r
-    orrne   r3, r3, #0x40      @ shadow by default\r
+    orrmi   r3, r3, #0x40      @ for sh/hi\r
 \r
     add     r6, r6, #1         @ inc now\r
     adds    r0, r2, #0         @ mov sx to r0 and set ZV flags\r
@@ -1101,14 +1248,14 @@ DrawSprite:
 \r
 .dspr_loop:\r
     subs    r6, r6, #1         @ width--\r
-    ldmeqfd sp!, {r4-r9,r11,pc}@ return\r
+    beq     DrawSprite\r
     adds    r0, r0, #8         @ sx+=8\r
     add     r8, r8, r5         @ tile+=delta\r
 \r
 .dspr_loop_enter:\r
     ble     .dspr_loop         @ sx <= 0\r
     cmp     r0, #328\r
-    ldmgefd sp!, {r4-r9,r11,pc}@ return\r
+    bge     DrawSprite\r
 \r
     mov     r8, r8, lsl #17\r
     mov     r8, r8, lsr #17    @ tile&=0x7fff; // Clip tile address\r
@@ -1137,6 +1284,10 @@ DrawSprite:
     TileFlip r12\r
     b       .dspr_loop\r
 \r
+.dspr_singlec_sh:\r
+    cmp     r2, #0xe0000000\r
+    bcs     .dspr_loop          @ operator tileline, ignore\r
+\r
 .dspr_SingleColor:\r
     and     r4, r2, #0xf\r
     orr     r4, r3, r4\r
@@ -1159,45 +1310,14 @@ DrawSprite:
 \r
     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
 .dspr_TileNorm_sh:\r
-    TileNormSh\r
+    TileNormSh_noop\r
     b       .dspr_loop\r
 \r
 .dspr_TileFlip_sh:\r
-    TileFlipSh\r
-    b       .dspr_loop\r
-\r
-.dspr_singlec_sh:\r
-    cmp     r2, #0xe0000000\r
-    bcc     .dspr_SingleColor   @ normal tileline\r
-    tst     r2, #0x10000000\r
-    bne     .dspr_sh_sh\r
-    TileSingleHi\r
-    b       .dspr_loop\r
-\r
-.dspr_sh_sh:\r
-    TileSingleSh\r
+    TileFlipSh_noop\r
     b       .dspr_loop\r
 \r
 \r
-.dspr_cache:\r
-    @ *(*hc)++ = (tile<<16)|((code&0x0800)<<5)|((sx<<6)&0x0000ffc0)|((code>>9)&0x30)|((sprite[0]>>24)&0xf);\r
-    mov     r4, r8, lsl #16     @ tile\r
-    tst     r9, #0x0800\r
-    orrne   r4, r4, #0x10000    @ code&0x0800\r
-    mov     r2, r2, lsl #22\r
-    orr     r4, r4, r2, lsr #16 @ (sx<<6)&0x0000ffc0\r
-    and     r2, r9, #0x6000\r
-    orr     r4, r4, r2, lsr #9  @ (code>>9)&0x30\r
-    mov     r3, r3, lsl #12\r
-    ldr     r2, [r1]\r
-    orr     r4, r4, r3, lsr #28 @ (sprite[0]>>24)&0xf\r
-\r
-    str     r4, [r2], #4\r
-    str     r2, [r1]\r
-\r
-    ldmfd   sp!, {r4-r9,r11,lr}\r
-    bx      lr\r
-\r
 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
 \r
 .global DrawWindow @ int tstart, int tend, int prio, int sh // int *hcache\r
@@ -1206,7 +1326,7 @@ DrawWindow:
     stmfd   sp!, {r4-r11,lr}\r
 \r
     ldr     r11, =(Pico+0x22228)  @ Pico.video\r
-    ldr     r10, =Scanline\r
+    ldr     r10, =DrawScanline\r
     ldrb    r12, [r11, #3]        @ pvid->reg[3]\r
 \r
     ldr     r10, [r10]\r
@@ -1226,19 +1346,18 @@ DrawWindow:
 \r
     ldr     r6, =rendstatus\r
     ldr     lr, =(Pico+0x10000) @ lr=Pico.vram\r
-    ldrb    r6, [r6]\r
+    ldr     r6, [r6]\r
 \r
     @ fetch the first code now\r
     ldrh    r7, [lr, r12]\r
 \r
-    ands    r6, r6, #2            @ we care about bit 1 only\r
+    ands    r6, r6, #PDRAW_WND_DIFF_PRIO\r
     orr     r6, r6, r2\r
-    bne     .dw_no_sameprio\r
 \r
-    cmp     r2, r7, lsr #15\r
-    ldmnefd sp!, {r4-r11,pc}      @ assume that whole window uses same priority\r
+    eoreq   r8, r2, r7, lsr #15   @ do prio bits differ?\r
+    cmpeq   r8, #1\r
+    ldmeqfd sp!, {r4-r11,pc}      @ yes, assume that whole window uses same priority\r
 \r
-.dw_no_sameprio:\r
     orr     r6, r6, r3, lsl #8    @ shadow mode\r
 \r
     sub     r8, r1, r0\r
@@ -1255,11 +1374,11 @@ DrawWindow:
     mov     r8, r8, lsl #1        @ cells\r
     mvn     r9, #0                @ r9=prevcode=-1\r
 .endif\r
-    add     r1, r11, r0, lsl #4 @ r1=pdest\r
+    add     r1, r11, r0, lsl #4   @ r1=pdest\r
     mov     r0, #0xf\r
     b       .dwloop_enter\r
 \r
-    @ r4,r5 & r7 are scratch in this loop\r
+    @ r4,r5 are scratch in this loop\r
 .dwloop:\r
     add     r1, r1, #8\r
 .dwloop_nor1:\r
@@ -1325,24 +1444,13 @@ DrawWindow:
     orreq   r3, r3, #0x40\r
     beq     .dw_shadow_done\r
     ldr     r4, [r1]\r
-    tst     r4, #0x00000080\r
-    biceq   r4, r4, #0x000000c0\r
-    tst     r4, #0x00008000\r
-    biceq   r4, r4, #0x0000c000\r
-    tst     r4, #0x00800000\r
-    biceq   r4, r4, #0x00c00000\r
-    tst     r4, #0x80000000\r
-    biceq   r4, r4, #0xc0000000\r
+    mov     r5, #0x3f\r
+    orr     r5, r5, r5, lsl #8\r
+    orr     r5, r5, r5, lsl #16\r
+    and     r4, r4, r5\r
     str     r4, [r1]\r
     ldr     r4, [r1,#4]\r
-    tst     r4, #0x00000080\r
-    biceq   r4, r4, #0x000000c0\r
-    tst     r4, #0x00008000\r
-    biceq   r4, r4, #0x0000c000\r
-    tst     r4, #0x00800000\r
-    biceq   r4, r4, #0x00c00000\r
-    tst     r4, #0x80000000\r
-    biceq   r4, r4, #0xc0000000\r
+    and     r4, r4, r5\r
     str     r4, [r1,#4]\r
     b       .dw_shadow_done\r
 \r
@@ -1452,23 +1560,29 @@ FinalizeLineBGR444:
     bne     .fl_loopcpBGR444_hi\r
 \r
     sub     r3, r4, #0x40*3*2\r
+    mov     r6, #1\r
 \r
 \r
 .fl_noshBGR444:\r
+    ldr     r12,=rendstatus\r
+    eors    r6, r6, #1          @ sh is 0\r
+    ldr     r12,[r12]\r
+    mov     lr, #0xff\r
+    tstne   r12,#PDRAW_ACC_SPRITES\r
+\r
 .if OVERRIDE_HIGHCOL\r
     ldr     r1, =HighCol\r
-    mov     lr, #0xff\r
+    movne   lr, #0x3f\r
     ldr     r1, [r1]\r
     mov     lr, lr, lsl #1\r
     add     r1, r1, #8\r
 .else\r
     ldr     r1, =(HighCol+8)\r
-    mov     lr, #0xff\r
+    movne   lr, #0x3f\r
     mov     lr, lr, lsl #1\r
 .endif\r
 \r
 .fl_loopBGR444:\r
-\r
     ldr     r12, [r1], #4\r
     subs    r2, r2, #1\r
 \r
@@ -1478,11 +1592,10 @@ FinalizeLineBGR444:
     ldrh    r5, [r3, r5]\r
     and     r6, lr, r12, lsr #15\r
     ldrh    r6, [r3, r6]\r
+    and     r12,lr, r12, lsr #23\r
+    ldrh    r12,[r3, r12]              @ 1c.i.\r
     orr     r4, r4, r5, lsl #16\r
-\r
-    and     r5, lr, r12, lsr #23\r
-    ldrh    r5, [r3, r5]              @ 2c.i.\r
-    orr     r5, r6, r5, lsl #16\r
+    orr     r5, r6, r12,lsl #16\r
 \r
     stmia   r0!, {r4,r5}\r
     bne     .fl_loopBGR444\r
@@ -1617,8 +1730,16 @@ FinalizeLineRGB555:
     bne     .fl_loopcpRGB555_hi\r
 \r
     sub     r3, r3, #0x40*2\r
+    mov     r6, #1\r
 \r
 .fl_noshRGB555:\r
+    ldr     r12,=rendstatus\r
+    eors    r6, r6, #1          @ sh is 0\r
+    ldr     r12,[r12]\r
+    mov     lr, #0xff\r
+    tstne   r12,#PDRAW_ACC_SPRITES\r
+    movne   lr, #0x3f\r
+\r
 .if OVERRIDE_HIGHCOL\r
     ldr     r1, =HighCol\r
     ldr     r0, =DrawLineDest\r
@@ -1632,7 +1753,6 @@ FinalizeLineRGB555:
 .endif\r
 \r
     ldrb    r12, [r8, #12]\r
-    mov     lr, #0xff\r
     mov     lr, lr, lsl #1\r
 \r
     tst     r12, #1\r