@ assembly "optimized" version of some funtions from draw.c
@ this is highly specialized, be careful if changing related C code!

@ (c) Copyright 2006, notaz
@ All Rights Reserved


.extern Pico
.extern PicoOpt
.extern HighCol
.extern Scanline
.extern HighSprZ
.extern rendstatus
.extern DrawLineDest
.extern DrawStripVSRam
.extern DrawStripInterlace


@ helper
.macro TilePixel pat lsrr offs
.if !\lsrr
    ands    r4, \pat, r2
.else
    ands    r4, \pat, r2, lsr #\lsrr
.endif
    orrne   r4, r3, r4
    strneb  r4, [r1,#\offs]
.endm

@ TileNorm (r1=pdest, r2=pixels8, r3=pal) r4: scratch, pat: register with helper pattern 0xf
.macro TileNorm pat
    TilePixel \pat, 12, 0         @ #0x0000f000
    TilePixel \pat,  8, 1         @ #0x00000f00
    TilePixel \pat,  4, 2         @ #0x000000f0
    TilePixel \pat,  0, 3         @ #0x0000000f
    TilePixel \pat, 28, 4         @ #0xf0000000
    TilePixel \pat, 24, 5         @ #0x0f000000
    TilePixel \pat, 20, 6         @ #0x00f00000
    TilePixel \pat, 16, 7         @ #0x000f0000
.endm

@ TileFlip (r1=pdest, r2=pixels8, r3=pal) r4: scratch, pat: register with helper pattern 0xf
.macro TileFlip pat
    TilePixel \pat, 16, 0         @ #0x000f0000
    TilePixel \pat, 20, 1         @ #0x00f00000
    TilePixel \pat, 24, 2         @ #0x0f000000
    TilePixel \pat, 28, 3         @ #0xf0000000
    TilePixel \pat,  0, 4         @ #0x0000000f
    TilePixel \pat,  4, 5         @ #0x000000f0
    TilePixel \pat,  8, 6         @ #0x00000f00
    TilePixel \pat, 12, 7         @ #0x0000f000
.endm

@ shadow/hilight mode

@ this one is for hi priority layer
.macro TilePixelShHP pat lsrr offs
    TilePixel \pat, \lsrr, \offs
    ldreqb  r4, [r1,#\offs]
    tsteq   r4, #0x80
    andeq   r4, r4, #0x3f
    streqb  r4, [r1,#\offs]
.endm

@ TileNorm (r1=pdest, r2=pixels8, r3=pal) r4: scratch, pat: register with helper pattern 0xf
.macro TileNormShHP pat
    TilePixelShHP \pat, 12, 0         @ #0x0000f000
    TilePixelShHP \pat,  8, 1         @ #0x00000f00
    TilePixelShHP \pat,  4, 2         @ #0x000000f0
    TilePixelShHP \pat,  0, 3         @ #0x0000000f
    TilePixelShHP \pat, 28, 4         @ #0xf0000000
    TilePixelShHP \pat, 24, 5         @ #0x0f000000
    TilePixelShHP \pat, 20, 6         @ #0x00f00000
    TilePixelShHP \pat, 16, 7         @ #0x000f0000
.endm

@ TileFlip (r1=pdest, r2=pixels8, r3=pal) r4: scratch, pat: register with helper pattern 0xf
.macro TileFlipShHP pat
    TilePixelShHP \pat, 16, 0         @ #0x000f0000
    TilePixelShHP \pat, 20, 1         @ #0x00f00000
    TilePixelShHP \pat, 24, 2         @ #0x0f000000
    TilePixelShHP \pat, 28, 3         @ #0xf0000000
    TilePixelShHP \pat,  0, 4         @ #0x0000000f
    TilePixelShHP \pat,  4, 5         @ #0x000000f0
    TilePixelShHP \pat,  8, 6         @ #0x00000f00
    TilePixelShHP \pat, 12, 7         @ #0x0000f000
.endm


@ TileSingleSh (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=sx; r12: helper pattern 0xf
.macro TileSingleSh
    tst     r0, #1              @ not aligned?
    mov     r7, #0x00c000
    orr     r7, r7, #0xc0
    ldrneb  r4, [r1]
    ldreqh  r4, [r1]
    orr     r4, r4, r7
    strneb  r4, [r1], #1
    streqh  r4, [r1], #2
    ldrh    r4, [r1]
    orr     r4, r4, r7
    strh    r4, [r1], #2
    ldrh    r4, [r1]
    orr     r4, r4, r7
    strh    r4, [r1], #2
    ldrh    r4, [r1]
    orr     r4, r4, r7
    strh    r4, [r1], #2
    ldrneb  r4, [r1]
    orr     r4, r4, r7
    strneb  r4, [r1], #1
.endm

@ TileSingleHi (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=sx, r12: register with helper pattern 0xf
.macro TileSingleHi
    tst     r1, #1              @ not aligned?
    mov     r7, #0x008000
    orr     r7, r7, #0x80
    ldrneb  r4, [r1]
    ldreqh  r4, [r1]
    bic     r4, r4, r7, lsr #1
    orr     r4, r4, r7
    strneb  r4, [r1], #1
    streqh  r4, [r1], #2
    ldrh    r4, [r1]
    bic     r4, r4, r7, lsr #1
    orr     r4, r4, r7
    strh    r4, [r1], #2
    ldrh    r4, [r1]
    bic     r4, r4, r7, lsr #1
    orr     r4, r4, r7
    strh    r4, [r1], #2
    ldrh    r4, [r1]
    bic     r4, r4, r7, lsr #1
    orr     r4, r4, r7
    strh    r4, [r1], #2
    ldrneb  r4, [r1]
    bic     r4, r4, r7, lsr #1
    orr     r4, r4, r7
    strneb  r4, [r1], #1
.endm

.macro TileDoShGenPixel shift ofs
.if \shift
    ands    r4, r12, r2, lsr #\shift
.else
    ands    r4, r12, r2
.endif
    beq     3f
    cmp     r4, #0xe
    beq     2f
    bgt     1f
    orr     r4, r3, r4
    strb    r4, [r1,#\ofs]
    b       3f
1:
    ldrb    r4, [r1,#\ofs]
    orr     r4, r4, #0xc0
    strb    r4, [r1,#\ofs]
    b       3f
2:
    ldrb    r4, [r1,#\ofs]
    bic     r4, r4, #0xc0
    orr     r4, r4, #0x80
    strb    r4, [r1,#\ofs]
3:
.endm

@ TileFlipSh (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=sx, r12: register with helper pattern 0xf
.macro TileFlipSh
    TileDoShGenPixel 16,  0 @ #0x000f0000
    TileDoShGenPixel 20,  1 @ #0x00f00000
    TileDoShGenPixel 24,  2 @ #0x0f000000
    TileDoShGenPixel 28,  3 @ #0xf0000000
    TileDoShGenPixel  0,  4 @ #0x0000000f
    TileDoShGenPixel  4,  5 @ #0x000000f0
    TileDoShGenPixel  8,  6 @ #0x00000f00
    TileDoShGenPixel 12,  7 @ #0x0000f000
.endm

@ TileNormSh (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=sx, r12: register with helper pattern 0xf
.macro TileNormSh
    TileDoShGenPixel 12,  0 @ #0x0000f000
    TileDoShGenPixel  8,  1 @ #0x00000f00
    TileDoShGenPixel  4,  2 @ #0x000000f0
    TileDoShGenPixel  0,  3 @ #0x0000000f
    TileDoShGenPixel 28,  4 @ #0xf0000000
    TileDoShGenPixel 24,  5 @ #0x0f000000
    TileDoShGenPixel 20,  6 @ #0x00f00000
    TileDoShGenPixel 16,  7 @ #0x000f0000
.endm


@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@ struct TileStrip
@ {
@   int nametab; // 0x00
@   int line;    // 0x04
@   int hscroll; // 0x08
@   int xmask;   // 0x0C
@   int *hc;     // 0x10 (pointer to cache buffer)
@   int cells;   // 0x14
@ };

@ int DrawLayer(int plane, int *hcache, int maxcells, int sh)

.global DrawLayer @ int plane, int *hcache, int maxcells, int sh

DrawLayer:
    stmfd   sp!, {r4-r11,lr}

    ldr     r11, =(Pico+0x22228)  @ Pico.video

    mov     r6, r1                @ hcache
    orr     r9, r2, r3, lsl #31   @ r9=maxcells|(sh<<31)

    ldrb    r7, [r11, #16]        @ ??hh??ww

    mov     r1, r7, lsl #4
    orr     r1, r1, #0x00ff

    and     r10, r7,  #3
    cmp     r10, #1
    biclt   r1,  r1, #0xfc00
    biceq   r1,  r1, #0xfe00
    bicgt   r1,  r1, #0xff00      @ r1=ymask=(height<<8)|0xff; ...; // Y Mask in pixels

    add     r10, r10, #5
    cmp     r10, #7
    subge   r10, r10, #1          @ r10=shift[width] (5,6,6,7)

    @ calculate xmask:
    mov     r8, #1
    mov     r5, r8, lsl r10
    sub     r5, r5, #1            @ r5=xmask

	@ Find name table:
    tst     r0,  r0
    ldreqb  r12, [r11, #2]
    moveq   r12, r12, lsl #10
    ldrneb  r12, [r11, #4]
    movne   r12, r12, lsl #13
    and     r12, r12, #(7<<13)    @ r12=(ts->nametab<<1) (halfword compliant)

    ldr     r2, =Scanline
    ldr     r2, [r2]
    ldr     lr, =(Pico+0x10000)   @ lr=Pico.vram

    ldrh    r8, [r11, #12]
    mov     r4, r8, lsr #8        @ pvid->reg[13]
    mov     r4, r4, lsl #10       @ htab=pvid->reg[13]<<9; (halfwords)
    ldrb    r7, [r11, #11]
    tst     r7, #2
    addne   r4, r4, r2, lsl #2    @ htab+=Scanline<<1; // Offset by line
    tst     r7, #1
    biceq   r4, r4, #0x1f         @ htab&=~0xf; // Offset by tile
    add     r4, r4, r0, lsl #1    @ htab+=plane
    bic     r4, r4, #0x00ff0000   @ just in case
    ldrh    r3, [lr, r4]          @ r3=hscroll

    tst     r7, #4
    bne     .DrawStrip_vsscroll

	@ Get vertical scroll value:
    add     r7, lr,  #0x012000
    add     r7, r7,  #0x000180    @ r7=Pico.vsram (Pico+0x22180)
    ldr     r7, [r7]

    tst     r8, #2
    tstne   r8, #4
    bne     .DrawStrip_interlace

    tst     r0, r0
    movne   r7, r7, lsr #16

    @ Find the line in the name table
    add     r2, r2, r7
    and     r2, r2, r1
    mov     r4, r2, lsr #3
    add     r10, r10, #1           @ shift[width]++
    add     r12, r12, r4, lsl r10  @ nametab+=(ts.line>>3)<<shift[width];

    @ ldmia   r0, {r1,r2,r3,r5,r6,r9} @ r2=line, r3=ts->hscroll, r5=ts->xmask, r6=ts->hc, r9=ts->cells
@    mov     r12,r1,  lsl #1 @ r12=(ts->nametab<<1) (halfword compliant)

    and     r10,r2,  #7
    mov     r10,r10, lsl #1 @ r10=ty=(ts->line&7)<<1;
    orr     r10,r10, r9, lsl #24

    rsb     r8, r3, #0
    mov     r8, r8, lsr #3  @ r8=tilex=(-ts->hscroll)>>3

    sub     r1, r3, #1
    and     r1, r1, #7
    add     r7, r1, #1      @ r7=dx=((ts->hscroll-1)&7)+1

    tst     r9, #1<<31
    mov     r3, #0
    orrne   r10,r10, #1<<23 @ r10=(cells<<24|sh<<23|hi_not_empty<<22|ty)
    movne   r3, #0x40       @ default to shadowed pal on sh mode

    mvn     r9, #0          @ r9=prevcode=-1

    cmp     r7, #8
    subeq   r10,r10, #0x01000000 @ we will loop cells+1 times, so loop less when there is no scroll

    @ cache some stuff to avoid mem access
    ldr     r11,=HighCol
    add     r1, r11, r7         @ r1=pdest
    mov     r0, #0xf
    b       .dsloop_enter

    @ r4 & r7 are scratch in this loop
.dsloop: @ 40-41 times
    add     r1, r1, #8
.dsloop_nor1:
    subs    r10,r10, #0x01000000
    add     r8, r8, #1
    bmi     .dsloop_exit

.dsloop_enter:
    and     r7, r5, r8
    add     r7, lr, r7, lsl #1 @ Pico.vram+((tilex&ts->xmask) as halfwords)
    ldrh    r7, [r7, r12]      @ r7=code (int, but from unsigned, no sign extend)

    tst     r7, #0x8000
    bne     .DrawStrip_hiprio

    cmp     r7, r9
    beq     .DrawStrip_samecode @ we know stuff about this tile already

    mov     r9, r7          @ remember code

    movs    r2, r9, lsl #20 @ if (code&0x1000)
    mov     r2, r2, lsl #1
@    bic     r7, r10,#0xff000000
@    add     r2, r7, r2, lsr #17 @ r2=addr=(code&0x7ff)<<4; addr+=ty
    add     r2, r2, r10, lsl #17
    mov     r2, r2, lsr #17
    eorcs   r2, r2, #0x0e   @ if (code&0x1000) addr^=0xe;

    bic     r7, r3, #0x3f
    and     r3, r9, #0x6000
    add     r3, r7, r3, lsr #9 @ r3=pal=((code&0x6000)>>9);

    ldr     r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels

.DrawStrip_samecode:
    tst     r2, r2
    beq     .dsloop              @ tileline blank

    cmp     r2, r2, ror #4
    beq     .DrawStrip_SingleColor @ tileline singlecolor 

    tst     r9, #0x0800
    beq     .DrawStrip_TileNorm

    @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r0: helper pattern
    TileFlip r0
    b       .dsloop

.DrawStrip_TileNorm:
    TileNorm r0
    b       .dsloop

.DrawStrip_SingleColor:
    and     r4, r2, #0xf
    orr     r4, r3, r4
    orr     r4, r4, r4, lsl #8
    tst     r1, #1             @ not aligned?
    strneb  r4, [r1], #1
    streqh  r4, [r1], #2
    strh    r4, [r1], #2
    strh    r4, [r1], #2
    strh    r4, [r1], #2
    strneb  r4, [r1], #1       @ have a remaining unaligned pixel?
    b       .dsloop_nor1       @ we incremeted r1 ourselves

.DrawStrip_hiprio:
    tst     r10, #0x00c00000
    beq     .DrawStrip_hiprio_maybempt
    sub     r0, r1, r11
    orr     r7, r7, r0,  lsl #16
    orr     r7, r7, r10, lsl #25 @ (ty<<25)
    tst     r7, #0x1000
    eorne   r7, r7, #7<<26  @ if(code&0x1000) cval^=7<<26;
    str     r7, [r6], #4    @ cache hi priority tile
    mov     r0, #0xf
    b       .dsloop

.DrawStrip_hiprio_maybempt:
    cmp     r7, r9
    beq     .dsloop         @ must've been empty, otherwise we wouldn't get here
    mov     r9, r7          @ remember code
    movs    r2, r9, lsl #20 @ if (code&0x1000)
    mov     r2, r2, lsl #1
    add     r2, r2, r10, lsl #17
    mov     r2, r2, lsr #17
    eorcs   r2, r2, #0x0e   @ if (code&0x1000) addr^=0xe;
    ldr     r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels
    tst     r2, r2
    orrne   r10, r10, #1<<22
    bne     .DrawStrip_hiprio
    b       .dsloop

.dsloop_exit:
    mov     r0, #0
    str     r0, [r6]    @ terminate the cache list

    ldmfd   sp!, {r4-r11,lr}
    bx      lr


.DrawStrip_vsscroll:
    @ shit, we have 2-cell column based vscroll
    @ let the c code handle this (for now)

    @   int nametab; // 0x00
    @   int line;    // 0x04
    @   int hscroll; // 0x08
    @   int xmask;   // 0x0C
    @   int *hc;     // 0x10 (pointer to cache buffer)
    @   int cells;   // 0x14

    sub     sp, sp, #6*4
    orr     r2, r1, r10, lsl #24 @ ts.line=ymask|(shift[width]<<24); // save some stuff instead of line
    mov     r1, r0               @ plane
    mov     r0, r12, lsr #1      @ halfwords
    and     r9, r9, #0xff
    stmia   sp, {r0,r2,r3,r5,r6,r9}

    mov     r0, sp
    bl      DrawStripVSRam @ struct TileStrip *ts, int plane

    add     sp, sp, #6*4
    ldmfd   sp!, {r4-r11,lr}
    bx      lr

@ interlace mode 2? Sonic 2?
.DrawStrip_interlace:
    tst     r0, r0
    moveq   r7, r7, lsl #21
    movne   r7, r7, lsl #5

    @ Find the line in the name table
    add     r2, r7, r2, lsl #22    @ r2=(vscroll+(Scanline<<1))<<21 (11 bits);
    orr     r1, r1, #0x80000000
    and     r2, r2, r1, ror #10    @ &((ymask<<1)|1)<<21;
    mov     r2, r2, lsr #21
    mov     r4, r2, lsr #4
    mov     r12, r12, lsr #1       @ halfwords
    add     r0, r12, r4, lsl r10   @ nametab+=(ts.line>>4)<<shift[width];
    and     r9, r9, #0xff

    sub     sp, sp, #6*4
    stmia   sp, {r0,r2,r3,r5,r6,r9}

    mov     r0, sp
    bl      DrawStripInterlace @ struct TileStrip *ts

    add     sp, sp, #6*4
    ldmfd   sp!, {r4-r11,lr}
    bx      lr

.pool

@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@


.global BackFill @ int reg7, int sh

BackFill:
    stmfd   sp!, {r4-r9,lr}

    ldr     lr, =(HighCol+8)

    mov     r0, r0, lsl #26
    mov     r0, r0, lsr #26
    orr     r0, r0, r1, lsl #6
    orr     r0, r0, r0, lsl #8
    orr     r0, r0, r0, lsl #16

    mov     r1, r0
    mov     r2, r0
    mov     r3, r0
    mov     r4, r0
    mov     r5, r0
    mov     r6, r0
    mov     r7, r0

    @ go go go!
    stmia   lr!, {r0-r7} @ 10*8*4
    stmia   lr!, {r0-r7}
    stmia   lr!, {r0-r7}
    stmia   lr!, {r0-r7}
    stmia   lr!, {r0-r7}
    stmia   lr!, {r0-r7}
    stmia   lr!, {r0-r7}
    stmia   lr!, {r0-r7}
    stmia   lr!, {r0-r7}
    stmia   lr!, {r0-r7}

    ldmfd   sp!, {r4-r9,r12}
    bx      r12


@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@


.global DrawTilesFromCache @ int *hc, int sh

DrawTilesFromCache:
    stmfd   sp!, {r4-r8,r11,lr}

    mvn     r5, #0         @ r5=prevcode=-1
    mov     r8, r1

    @ cache some stuff to avoid mem access
    ldr     r11,=HighCol
    ldr     lr, =(Pico+0x10000) @ lr=Pico.vram
    mov     r12,#0xf

    @ scratch: r4, r7
.dtfc_loop:
    ldr     r6, [r0], #4    @ read code
    movs    r1, r6, lsr #16 @ r1=dx;
    ldmeqfd sp!, {r4-r8,r11,pc} @ dx is never zero, this must be a terminator, return
    bic     r1, r1, #0xfe00
    add     r1, r11, r1     @ r1=pdest

@    tst     r8, r8
@    bne     .dtfc_shadow    @ this is a rare case, so we jump when it happens, not when it doesn't
@.dtfc_shadow_done:

    mov     r7, r6, lsl #16
    cmp     r5, r7, lsr #16
    beq     .dtfc_samecode  @ if (code==prevcode)

    mov     r5, r7, lsr #16

    mov     r2, r5, lsl #21
    mov     r2, r2, lsr #17 @ r2=addr=(code&0x7ff)<<4;
    add     r2, r2, r6, lsr #25 @ addr+=ty

    and     r3, r5, #0x6000
    mov     r3, r3, lsr #9  @ r3=pal=((code&0x6000)>>9);

    ldr     r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels

.dtfc_samecode:
    tst     r8, r8
    bne     .dtfc_shadow

    tst     r2, r2
    beq     .dtfc_loop

    cmp     r2, r2, ror #4
    beq     .dtfc_SingleColor @ tileline singlecolor 

    tst     r5, #0x0800
    beq     .dtfc_TileNorm

    @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern
    TileFlip r12
    b       .dtfc_loop

.dtfc_TileNorm:
    TileNorm r12
    b       .dtfc_loop

.dtfc_SingleColor:
    and     r4, r2, #0xf
    orr     r4, r3, r4
    orr     r4, r4, r4, lsl #8
    tst     r1, #1              @ not aligned?
    strneb  r4, [r1], #1
    streqh  r4, [r1], #2
    strh    r4, [r1], #2
    strh    r4, [r1], #2
    strh    r4, [r1], #2
    strneb  r4, [r1], #1        @ have a remaining unaligned pixel?
    b       .dtfc_loop

.dtfc_shadow:
    tst     r2, r2
    beq     .dtfc_shadow_blank

    cmp     r2, r2, ror #4
    beq     .dtfc_SingleColor @ tileline singlecolor 

    tst     r5, #0x0800
    beq     .dtfc_TileNormShHP

    @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern
    TileFlipShHP r12
    b       .dtfc_loop

.dtfc_TileNormShHP:
    TileNormShHP r12
    b       .dtfc_loop

.dtfc_shadow_blank:
    ldrb    r4, [r1]
    tst     r4, #0x80
    andeq   r4, r4,#0x3f
    streqb  r4, [r1]
    ldrb    r4, [r1,#1]
    tst     r4, #0x80
    andeq   r4, r4,#0x3f
    streqb  r4, [r1,#1]
    ldrb    r4, [r1,#2]
    tst     r4, #0x80
    andeq   r4, r4,#0x3f
    streqb  r4, [r1,#2]
    ldrb    r4, [r1,#3]
    tst     r4, #0x80
    andeq   r4, r4,#0x3f
    streqb  r4, [r1,#3]
    ldrb    r4, [r1,#4]
    tst     r4, #0x80
    andeq   r4, r4,#0x3f
    streqb  r4, [r1,#4]
    ldrb    r4, [r1,#5]
    tst     r4, #0x80
    andeq   r4, r4,#0x3f
    streqb  r4, [r1,#5]
    ldrb    r4, [r1,#6]
    tst     r4, #0x80
    andeq   r4, r4,#0x3f
    streqb  r4, [r1,#6]
    ldrb    r4, [r1,#7]
    tst     r4, #0x80
    andeq   r4, r4,#0x3f
    streqb  r4, [r1,#7]
    b       .dtfc_loop

.pool

@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@


.global DrawSpritesFromCache @ int *hc, int sh

DrawSpritesFromCache:
    stmfd   sp!, {r4-r11,lr}

    @ cache some stuff to avoid mem access
    ldr     r11,=HighCol
    ldr     lr, =(Pico+0x10000) @ lr=Pico.vram
    mov     r6, r1, lsl #31
    orr     r6, r6, #1<<30
    mov     r12,#0xf

    mov     r10, r0

.dsfc_loop:
    ldr     r9, [r10], #4    @ read code
    tst     r9, r9
    ldmeqfd sp!, {r4-r11,pc}

    mov     r4, r9, lsl #28
    bic     r6, r6, #7
    orr     r6, r6, r4, lsr #30
    add     r6, r6, #1       @ r6=s1cc???? ... ?????www (s=shadow/hilight, cc=pal, w=width)

    and     r5, r9, #3
    add     r5, r5, #1       @ r5=delta
    tst     r9, #0x10000
    rsbne   r5, r5, #0       @ Flip X
    mov     r5, r5, lsl #4

    mov     r2, r9, lsr #17
    mov     r8, r2, lsl #1   @ tile=((unsigned int)code>>17)<<1;

    and     r3, r9, #0x30    @ r3=pal=(code&0x30);

    bic     r6, r6, #3<<28
    orr     r6, r6, r3, lsl #24

    mov     r0, r9, lsl #16
    mov     r0, r0, asr #22  @ sx=(code<<16)>>22
    adds    r0, r0, #0       @ set ZV
    b       .dsfc_inloop_enter

@ scratch: r4, r7
.dsfc_inloop:
    sub     r6, r6, #1
    tst     r6, #7
    beq     .dsfc_loop
    adds    r0, r0, #8
    add     r8, r8, r5

.dsfc_inloop_enter:
    ble     .dsfc_inloop
    cmp     r0, #328
    bge     .dsfc_loop

    mov     r8, r8, lsl #17
    mov     r8, r8, lsr #17   @ tile&=0x7fff; // Clip tile address

    ldr     r2, [lr, r8, lsl #1] @ pack=*(unsigned int *)(Pico.vram+tile); // Get 8 pixels
    tst     r2, r2
    beq     .dsfc_inloop

    add     r1, r11, r0       @ r1=pdest

    cmp     r12, r6, lsr #28
    beq     .dsfc_shadow

    cmp     r2, r2, ror #4
    beq     .dsfc_SingleColor @ tileline singlecolor 

    tst     r9, #0x10000
    beq     .dsfc_TileNorm

    @ TileFlip (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern
    TileFlip r12
    b       .dsfc_inloop

.dsfc_TileNorm:
    TileNorm r12
    b       .dsfc_inloop

.dsfc_SingleColor:
    tst     r0, #1              @ not aligned?
    and     r4, r2, #0xf
    orr     r4, r3, r4
    orr     r4, r4, r4, lsl #8
    strneb  r4, [r1], #1
    streqh  r4, [r1], #2
    strh    r4, [r1], #2
    strh    r4, [r1], #2
    strh    r4, [r1], #2
    strneb  r4, [r1], #1
    b       .dsfc_inloop

.dsfc_shadow:
    cmp     r2, r2, ror #4
    beq     .dsfc_singlec_sh

    tst     r9, #0x10000
    beq     .dsfc_TileNorm_sh

    @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern
    TileFlipSh
    b       .dsfc_inloop

.dsfc_TileNorm_sh:
    TileNormSh
    b       .dsfc_inloop

.dsfc_singlec_sh:
    cmp     r2, #0xe0000000
    bcc     .dsfc_SingleColor   @ normal singlecolor tileline (carry inverted in ARM)
    tst     r2, #0x10000000
    bne     .dsfc_sh_sh
    TileSingleHi
    b       .dsfc_inloop

.dsfc_sh_sh:
    TileSingleSh
    b       .dsfc_inloop

.pool

@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@ + 0  :    hhhhvvvv ab--hhvv yyyyyyyy yyyyyyyy // a: offscreen h, b: offs. v, h: horiz. size
@ + 4  :    xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8

.global DrawSprite @ unsigned int *sprite, int **hc, int sh

DrawSprite:
    stmfd   sp!, {r4-r9,r11,lr}

    ldr     r3, [r0]        @ sprite[0]
    mov     r6, r3, lsr #28
    sub     r6, r6, #1      @ r6=width-1 (inc later)
    mov     r5, r3, lsr #24
    and     r5, r5, #7      @ r5=height

    mov     r4, r3, lsl #16 @ r4=sy<<16 (tmp)

    ldr     r7, =Scanline
    ldr     r7, [r7]
    sub     r7, r7, r4, asr #16 @ r7=row=Scanline-sy

    tst     r2, r2
    ldr     r9, [r0, #4]
    mov     r2, r9, asr #16 @ r2=sx
    bic     r9, r9, #0xfe000000
    orrne   r9, r9, #1<<31  @ r9=code|(sh<<31)

    tst     r9, #0x1000
    movne   r4, r5, lsl #3
    subne   r4, r4, #1
    subne   r7, r4, r7      @ if (code&0x1000) row=(height<<3)-1-row; // Flip Y

    mov     r8, r9, lsl #21
    mov     r8, r8, lsr #21
    add     r8, r8, r7, lsr #3 @ tile+=row>>3; // Tile number increases going down
    
    tst     r9, #0x0800
    mlane   r8, r5, r6, r8  @ if (code&0x0800) { tile+=delta*(width-1);
    rsbne   r5, r5, #0      @ delta=-delta; } // r5=delta now

    mov     r8, r8, lsl #4
    and     r7, r7, #7
    add     r8, r8, r7, lsl #1 @ tile+=(row&7)<<1; // Tile address

    tst     r9, #0x8000
    bne     .dspr_cache       @ if(code&0x8000) // high priority - cache it

    @ cache some stuff to avoid mem access
    ldr     r11,=HighCol
    ldr     lr, =(Pico+0x10000) @ lr=Pico.vram
    mov     r12,#0xf

    mov     r5, r5, lsl #4     @ delta<<=4; // Delta of address
    and     r4, r9, #0x6000
    orr     r9, r9, r4, lsl #16
    orr     r9, r9, #0x10000000 @ r9=scc1 ???? ... <code> (s=shadow/hilight, cc=pal)

    tst     r9, #1<<31
    mov     r3, r4, lsr #9     @ r3=pal=((code>>9)&0x30);
    orrne   r3, r3, #0x40      @ shadow by default

    add     r6, r6, #1         @ inc now
    adds    r0, r2, #0         @ mov sx to r0 and set ZV flags
    b       .dspr_loop_enter

.dspr_loop:
    subs    r6, r6, #1         @ width--
    ldmeqfd sp!, {r4-r9,r11,pc}@ return
    adds    r0, r0, #8         @ sx+=8
    add     r8, r8, r5         @ tile+=delta

.dspr_loop_enter:
    ble     .dspr_loop         @ sx <= 0
    cmp     r0, #328
    ldmgefd sp!, {r4-r9,r11,pc}@ return

    mov     r8, r8, lsl #17
    mov     r8, r8, lsr #17    @ tile&=0x7fff; // Clip tile address

    ldr     r2, [lr, r8, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels
    tst     r2, r2
    beq     .dspr_loop

    add     r1, r11, r0        @ r1=pdest

    cmp     r12, r9, lsr #28
    beq     .dspr_shadow

    cmp     r2, r2, ror #4
    beq     .dspr_SingleColor @ tileline singlecolor 

    tst     r9, #0x0800
    beq     .dspr_TileNorm

    @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern
    TileFlip r12
    b       .dspr_loop

@ scratch: r4, r7
.dspr_TileNorm:
    TileNorm r12
    b       .dspr_loop

.dspr_SingleColor:
    and     r4, r2, #0xf
    orr     r4, r3, r4
    orr     r4, r4, r4, lsl #8
    tst     r0, #1              @ not aligned?
    strneb  r4, [r1], #1
    streqh  r4, [r1], #2
    strh    r4, [r1], #2
    strh    r4, [r1], #2
    strh    r4, [r1], #2
    strneb  r4, [r1], #1
    b       .dspr_loop

.dspr_shadow:
    cmp     r2, r2, ror #4
    beq     .dspr_singlec_sh

    tst     r9, #0x0800
    beq     .dspr_TileNorm_sh

    @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern
    TileFlipSh
    b       .dspr_loop

.dspr_TileNorm_sh:
    TileNormSh
    b       .dspr_loop

.dspr_singlec_sh:
    cmp     r2, #0xe0000000
    bcc     .dspr_SingleColor   @ normal tileline
    tst     r2, #0x10000000
    bne     .dspr_sh_sh
    TileSingleHi
    b       .dspr_loop

.dspr_sh_sh:
    TileSingleSh
    b       .dspr_loop


.dspr_cache:
    @ *(*hc)++ = (tile<<16)|((code&0x0800)<<5)|((sx<<6)&0x0000ffc0)|((code>>9)&0x30)|((sprite[0]>>24)&0xf);
    mov     r4, r8, lsl #16     @ tile
    tst     r9, #0x0800
    orrne   r4, r4, #0x10000    @ code&0x0800
    mov     r2, r2, lsl #22
    orr     r4, r4, r2, lsr #16 @ (sx<<6)&0x0000ffc0
    and     r2, r9, #0x6000
    orr     r4, r4, r2, lsr #9  @ (code>>9)&0x30
    mov     r2, r3, lsl #12
    orr     r4, r4, r2, lsr #28 @ (sprite[0]>>24)&0xf

    ldr     r2, [r1]
    str     r4, [r2], #4
    str     r2, [r1]

    ldmfd   sp!, {r4-r9,r11,lr}
    bx      lr

@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

.global DrawWindow @ int tstart, int tend, int prio, int sh // int *hcache

DrawWindow:
    stmfd   sp!, {r4-r11,lr}

    ldr     r11, =(Pico+0x22228)  @ Pico.video
    ldrb    r12, [r11, #3]        @ pvid->reg[3]
    mov     r12, r12, lsl #10

    ldr     r10, =Scanline
    ldr     r10, [r10]
    mov     r5, r10, lsr #3
    and     r10, r10, #7
    mov     r10, r10, lsl #1      @ r10=ty

    ldr     r4, [r11, #12]
    tst     r4, #1                @ 40 cell mode?
    andne   r12, r12, #0xf000     @ 0x3c<<10
    andeq   r12, r12, #0xf800
    addne   r12, r12, r5, lsl #7
    addeq   r12, r12, r5, lsl #6  @ nametab
    add     r12, r12, r0, lsl #2  @ +starttile

    ldr     lr, =(Pico+0x10000) @ lr=Pico.vram

    @ fetch the first code now
    ldrh    r7, [lr, r12]

    ldr     r6, =rendstatus
    ldrb    r6, [r6]
    ands    r6, r6, #2            @ we care about bit 1 only
    orr     r6, r6, r2
    bne     .dw_no_sameprio

    cmp     r2, r7, lsr #15
    ldmnefd sp!, {r4-r11,pc}      @ assume that whole window uses same priority

.dw_no_sameprio:
    orr     r6, r6, r3, lsl #8    @ shadow mode

    sub     r8, r1, r0
    mov     r8, r8, lsl #1        @ cells

    mvn     r9, #0                @ r9=prevcode=-1

    @ cache some stuff to avoid mem access
    ldr     r11,=(HighCol+8)
    add     r1, r11, r0, lsl #4 @ r1=pdest
    mov     r0, #0xf
    b       .dwloop_enter

    @ r4,r5 & r7 are scratch in this loop
.dwloop:
    add     r1, r1, #8
.dwloop_nor1:
    subs    r8, r8, #1
    add     r12, r12, #2    @ halfwords
    beq     .dwloop_end     @ done

    ldrh    r7, [lr, r12]   @ r7=code (int, but from unsigned, no sign extend)

    eor     r5, r6, r7, lsr #15
    tst     r5, #1
    orrne   r6, r6, #2      @ wrong pri
    bne     .dwloop

    cmp     r7, r9
    beq     .dw_samecode    @ we know stuff about this tile already

.dwloop_enter:
    mov     r9, r7          @ remember code

    movs    r2, r9, lsl #20 @ if (code&0x1000)
    mov     r2, r2, lsl #1
    add     r2, r10, r2, lsr #17 @ r2=addr=(code&0x7ff)<<4; addr+=ty
    eorcs   r2, r2, #0x0e   @ if (code&0x1000) addr^=0xe;

    and     r3, r9, #0x6000
    mov     r3, r3, lsr #9  @ r3=pal=((code&0x6000)>>9);

    ldr     r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels

.dw_samecode:
    tst     r6, #0x100
    bne     .dw_shadow
.dw_shadow_done:
    tst     r2, r2
    beq     .dwloop              @ tileline blank

    cmp     r2, r2, ror #4
    beq     .dw_SingleColor @ tileline singlecolor 

    tst     r9, #0x0800
    beq     .dw_TileNorm

    @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r0: helper pattern
    TileFlip r0
    b       .dwloop

.dw_TileNorm:
    TileNorm r0
    b       .dwloop

.dw_SingleColor:
    and     r4, r0, r2         @ #0x0000000f
    orr     r4, r3, r4
    orr     r4, r4, r4, lsl #8
    orr     r4, r4, r4, lsl #16
    mov     r5, r4
    stmia   r1!, {r4,r5}
    b       .dwloop_nor1       @ we incremeted r1 ourselves

.dw_shadow:
    tst     r6, #1             @ hi pri?
    orreq   r3, r3, #0x40
    beq     .dw_shadow_done
    ldr     r4, [r1]
    tst     r4, #0x00000080
    biceq   r4, r4, #0x000000c0
    tst     r4, #0x00008000
    biceq   r4, r4, #0x0000c000
    tst     r4, #0x00800000
    biceq   r4, r4, #0x00c00000
    tst     r4, #0x80000000
    biceq   r4, r4, #0xc0000000
    str     r4, [r1]
    ldr     r4, [r1,#4]
    tst     r4, #0x00000080
    biceq   r4, r4, #0x000000c0
    tst     r4, #0x00008000
    biceq   r4, r4, #0x0000c000
    tst     r4, #0x00800000
    biceq   r4, r4, #0x00c00000
    tst     r4, #0x80000000
    biceq   r4, r4, #0xc0000000
    str     r4, [r1,#4]
    b       .dw_shadow_done

.dwloop_end:
    ldr     r0, =rendstatus
    ldr     r1, [r0]
    and     r6, r6, #2
    orr     r1, r1, r6
    str     r1, [r0]

    ldmfd   sp!, {r4-r11,r12}
    bx      r12


@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@


@ hilights 2 pixels in RGB444/BGR444 format
.macro TileDoShHi2Pixels444 reg
    mov     \reg, \reg, ror #12
    adds    \reg, \reg, #0x40000000
    orrcs   \reg, \reg, #0xf0000000
    mov     \reg, \reg, ror #28
    adds    \reg, \reg, #0x40000000
    orrcs   \reg, \reg, #0xf0000000
    mov     \reg, \reg, ror #28
    adds    \reg, \reg, #0x40000000
    orrcs   \reg, \reg, #0xf0000000
    mov     \reg, \reg, ror #24
    adds    \reg, \reg, #0x40000000
    orrcs   \reg, \reg, #0xf0000000
    mov     \reg, \reg, ror #28
    adds    \reg, \reg, #0x40000000
    orrcs   \reg, \reg, #0xf0000000
    mov     \reg, \reg, ror #28
    adds    \reg, \reg, #0x40000000
    orrcs   \reg, \reg, #0xf0000000
    mov     \reg, \reg, ror #12
.endm


.global FinalizeLineBGR444 @ int sh

FinalizeLineBGR444:
    stmfd   sp!, {r4-r6,lr}
    mov     r6, r0
    ldr     r0, =DrawLineDest
    ldr     r0, [r0]
    ldr     lr, =(Pico+0x22228)  @ Pico.video
    sub     r3, lr, #0x128       @ r3=Pico.cram

    ldrb    r12, [lr, #12]
    tst     r12, #1
    movne   r2, #320/4           @ len
    moveq   r2, #256/4
    addeq   r0, r0, #32*2
    ldreq   r4, =PicoOpt
    ldreq   r4, [r4]
    tsteq   r4, #0x100
    addeq   r0, r0, #32*2

    tst     r6, r6
    beq     .fl_noshBGR444

    ldr     r4, =HighPal

    ldrb    r12, [lr, #-0x1a]      @ 0x2220e ~ dirtyPal
    tst     r12, r12
    moveq   r3, r4
    beq     .fl_noshBGR444
    mov     r12, #0
    strb    r12, [lr, #-0x1a]

    mov     lr, #0x40/8
    @ copy pal:
.fl_loopcpBGR444:
    subs    lr, lr, #1
    ldmia   r3!, {r1,r5,r6,r12}
    stmia   r4!, {r1,r5,r6,r12}
    bne     .fl_loopcpBGR444

    @ shadowed pixels:
    mov     r12,    #0x0077
    orr     r12,r12,#0x0700
    orr     r12,r12,r12,lsl #16
    sub     r3, r3, #0x40*2
    add     r5, r4, #0x80*2
    mov     lr, #0x40/4
.fl_loopcpBGR444_sh:
    subs    lr, lr, #1
    ldmia   r3!, {r1,r6}
    and     r1, r12, r1, lsr #1
    and     r6, r12, r6, lsr #1
    stmia   r4!, {r1,r6}
    stmia   r5!, {r1,r6}
    bne     .fl_loopcpBGR444_sh

    @ hilighted pixels:
    sub     r3, r3, #0x40*2
    mov     lr, #0x40/2
.fl_loopcpBGR444_hi:
    ldr     r1, [r3], #4
    TileDoShHi2Pixels444 r1
    str     r1, [r4], #4
    subs    lr, lr, #1
    bne     .fl_loopcpBGR444_hi

    sub     r3, r4, #0x40*3*2


.fl_noshBGR444:
    ldr     r1, =(HighCol+8)
    mov     lr, #0xff
    mov     lr, lr, lsl #1

.fl_loopBGR444:
    subs    r2, r2, #1

    ldr     r12, [r1], #4

    and     r4, lr, r12, lsl #1
    ldrh    r4, [r3, r4]
    and     r5, lr, r12, lsr #7
    ldrh    r5, [r3, r5]
    orr     r4, r4, r5, lsl #16

    and     r5, lr, r12, lsr #15
    ldrh    r5, [r3, r5]
    and     r6, lr, r12, lsr #23
    ldrh    r6, [r3, r6]
    orr     r5, r5, r6, lsl #16

    stmia   r0!, {r4,r5}
    bne     .fl_loopBGR444


    ldmfd   sp!, {r4-r6,lr}
    bx lr


@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@


@ hilights 2 pixels in RGB555/BGR555 format
.macro TileDoShHi2Pixels555 reg
    adds    \reg, \reg, #0x40000000
    orrcs   \reg, \reg, #0xf0000000
    mov     \reg, \reg, ror #27
    adds    \reg, \reg, #0x40000000
    orrcs   \reg, \reg, #0xf0000000
    mov     \reg, \reg, ror #26
    adds    \reg, \reg, #0x40000000
    orrcs   \reg, \reg, #0xf0000000
    mov     \reg, \reg, ror #27
    adds    \reg, \reg, #0x40000000
    orrcs   \reg, \reg, #0xf0000000
    mov     \reg, \reg, ror #27
    adds    \reg, \reg, #0x40000000
    orrcs   \reg, \reg, #0xf0000000
    mov     \reg, \reg, ror #26
    adds    \reg, \reg, #0x40000000
    orrcs   \reg, \reg, #0xf0000000
    mov     \reg, \reg, ror #27
.endm


@ Convert 0000bbb0 ggg0rrr0
@ to      rrrrrggg gggbbbbb

@ r2,r3,r9 - scratch, lr = 0x001c001c, r8 = 0x00030003
.macro convRGB565 reg
    and     r2,   lr,   \reg,lsl #1
    and     r9,   r8,   \reg,lsr #2
    orr     r2,   r2,   r9           @ r2=red
    and     r3,   lr,   \reg,lsr #7
    and     r9,   r8,   \reg,lsr #10
    orr     r3,   r3,   r9           @ r3=blue
    and     \reg, \reg, lr,  lsl #3
    orr     \reg, \reg, \reg,lsl #3  @ green
    orr     \reg, \reg, r2,  lsl #11 @ add red back
    orr     \reg, \reg, r3           @ add blue back
.endm

vidConvCpyRGB565: @ void *to, void *from, int pixels
    stmfd   sp!, {r4-r9,lr}

    mov     r12, r2, lsr #3 @ repeats
    mov     lr, #0x001c0000
    orr     lr, lr,  #0x01c  @ lr == pattern 0x001c001c
    mov     r8, #0x00030000
    orr     r8, r8,  #0x003  @ lr == pattern 0x001c001c

.loopRGB565:
	subs    r12, r12, #1

 	ldmia	r1!, {r4-r7}
    convRGB565 r4
    str     r4, [r0], #4
    convRGB565 r5
    str     r5, [r0], #4
    convRGB565 r6
    str     r6, [r0], #4
    convRGB565 r7
    str     r7, [r0], #4

    bgt     .loopRGB565

    ldmfd   sp!, {r4-r9,lr}
    bx      lr



.global FinalizeLineRGB555 @ int sh

FinalizeLineRGB555:
    stmfd   sp!, {r4-r8,lr}
    ldr     r5, =(Pico+0x22228)  @ Pico.video
    ldr     r4, =HighPal
    mov     r6, r0

    ldrb    r7, [r5, #-0x1a]     @ 0x2220e ~ dirtyPal
    tst     r7, r7
    beq     .fl_noconvRGB555
    mov     r1, #0
    strb    r1, [r5, #-0x1a]
    sub     r1, r5, #0x128       @ r1=Pico.cram
    mov     r0, r4
    mov     r2, #0x40
    bl      vidConvCpyRGB565

.fl_noconvRGB555:
    ldr     r0, =DrawLineDest
    ldr     r0, [r0]

    ldrb    r12, [r5, #12]
    tst     r12, #1
    movne   r2, #320/8           @ len
    moveq   r2, #256/8
    ldreq   r3, =PicoOpt
    ldreq   r3, [r3]
    tsteq   r3, #0x100
    addeq   r0, r0, #32*2

    mov     r3, r4
    tst     r6, r6
    beq     .fl_noshRGB555
    tst     r7, r7
    beq     .fl_noshRGB555

    @ shadowed pixels:
    mov     r12,    #0x008e
    orr     r12,r12,#0x7300
    orr     r12,r12,r12,lsl #16
    add     r4, r3, #0x40*2
    add     r5, r3, #0xc0*2
    mov     lr, #0x40/4
.fl_loopcpRGB555_sh:
    subs    lr, lr, #1
    ldmia   r3!, {r1,r6}
    and     r1, r12, r1, lsr #1
    and     r6, r12, r6, lsr #1
    stmia   r4!, {r1,r6}
    stmia   r5!, {r1,r6}
    bne     .fl_loopcpRGB555_sh

    @ hilighted pixels:
    sub     r3, r3, #0x40*2
    mov     lr, #0x40/2
.fl_loopcpRGB555_hi:
    ldr     r1, [r3], #4
    TileDoShHi2Pixels555 r1
    str     r1, [r4], #4
    subs    lr, lr, #1
    bne     .fl_loopcpRGB555_hi

    sub     r3, r3, #0x40*2


.fl_noshRGB555:
    ldr     r1, =(HighCol+8)
    mov     lr, #0xff
    mov     lr, lr, lsl #1

.fl_loopRGB555:
    subs    r2, r2, #1

    ldr     r12, [r1], #4
    ldr     r7,  [r1], #4

    and     r4, lr, r12, lsl #1
    ldrh    r4, [r3, r4]
    and     r5, lr, r12, lsr #7
    ldrh    r5, [r3, r5]
    orr     r4, r4, r5, lsl #16

    and     r5, lr, r12, lsr #15
    ldrh    r5, [r3, r5]
    and     r6, lr, r12, lsr #23
    ldrh    r6, [r3, r6]
    orr     r5, r5, r6, lsl #16

    and     r8, lr, r7, lsl #1
    ldrh    r8, [r3, r8]
    and     r6, lr, r7, lsr #7
    ldrh    r6, [r3, r6]
    orr     r8, r8, r6, lsl #16

    and     r12,lr, r7, lsr #15
    ldrh    r12,[r3, r12]
    and     r6, lr, r7, lsr #23
    ldrh    r6, [r3, r6]
    orr     r12,r12, r6, lsl #16

    stmia   r0!, {r4,r5,r8,r12}
    bne     .fl_loopRGB555


    ldmfd   sp!, {r4-r8,lr}
    bx lr

@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@ utility
.global blockcpy @ void *dst, void *src, size_t n

blockcpy:
    stmfd   sp!, {r4,r5}
    mov     r2, r2, lsr #4
blockcpy_loop:
    subs    r2, r2, #1
    ldmia   r1!, {r3-r5,r12}
    stmia   r0!, {r3-r5,r12}
    bne     blockcpy_loop
    ldmfd   sp!, {r4,r5}
    bx      lr


.global blockcpy_or @ void *dst, void *src, size_t n, int pat

blockcpy_or:
    stmfd   sp!, {r4-r6}
    orr     r3, r3, r3, lsl #8
    orr     r3, r3, r3, lsl #16
    mov     r2, r2, lsr #4
blockcpy_loop_or:
    subs    r2, r2, #1
    ldmia   r1!, {r4-r6,r12}
    orr     r4, r4, r3
    orr     r5, r5, r3
    orr     r6, r6, r3
    orr     r12,r12,r3
    stmia   r0!, {r4-r6,r12}
    bne     blockcpy_loop_or
    ldmfd   sp!, {r4-r6}
    bx      lr

