accurate_sprites performance improvement, PSP is untested
[picodrive.git] / Pico / Draw.s
1 @ vim:filetype=armasm\r
2 \r
3 @ assembly "optimized" version of some funtions from draw.c\r
4 @ this is highly specialized, be careful if changing related C code!\r
5 \r
6 @ (c) Copyright 2007, Grazvydas "notaz" Ignotas\r
7 @ All Rights Reserved\r
8 \r
9 .include "port_config.s"\r
10 \r
11 .extern Pico\r
12 .extern PicoOpt\r
13 .extern HighCol\r
14 .extern Scanline\r
15 .extern HighSprZ\r
16 .extern rendstatus\r
17 .extern DrawLineDest\r
18 .extern DrawStripInterlace\r
19 \r
20 \r
21 @ helper\r
22 .macro TilePixel pat lsrr offs\r
23 .if !\lsrr\r
24     ands    r4, \pat, r2\r
25 .else\r
26     ands    r4, \pat, r2, lsr #\lsrr\r
27 .endif\r
28     orrne   r4, r3, r4\r
29     strneb  r4, [r1,#\offs]\r
30 .endm\r
31 \r
32 @ TileNorm (r1=pdest, r2=pixels8, r3=pal) r4: scratch, pat: register with helper pattern 0xf\r
33 .macro TileNorm pat\r
34     TilePixel \pat, 12, 0         @ #0x0000f000\r
35     TilePixel \pat,  8, 1         @ #0x00000f00\r
36     TilePixel \pat,  4, 2         @ #0x000000f0\r
37     TilePixel \pat,  0, 3         @ #0x0000000f\r
38     TilePixel \pat, 28, 4         @ #0xf0000000\r
39     TilePixel \pat, 24, 5         @ #0x0f000000\r
40     TilePixel \pat, 20, 6         @ #0x00f00000\r
41     TilePixel \pat, 16, 7         @ #0x000f0000\r
42 .endm\r
43 \r
44 @ TileFlip (r1=pdest, r2=pixels8, r3=pal) r4: scratch, pat: register with helper pattern 0xf\r
45 .macro TileFlip pat\r
46     TilePixel \pat, 16, 0         @ #0x000f0000\r
47     TilePixel \pat, 20, 1         @ #0x00f00000\r
48     TilePixel \pat, 24, 2         @ #0x0f000000\r
49     TilePixel \pat, 28, 3         @ #0xf0000000\r
50     TilePixel \pat,  0, 4         @ #0x0000000f\r
51     TilePixel \pat,  4, 5         @ #0x000000f0\r
52     TilePixel \pat,  8, 6         @ #0x00000f00\r
53     TilePixel \pat, 12, 7         @ #0x0000f000\r
54 .endm\r
55 \r
56 @ shadow/hilight mode\r
57 \r
58 @ this one is for hi priority layer\r
59 .macro TilePixelShHP lsrr offs\r
60 .if !\lsrr\r
61     ands    r4, r12, r2\r
62 .else\r
63     ands    r4, r12, r2, lsr #\lsrr\r
64 .endif\r
65     ldreqb  r4, [r1,#\offs]\r
66     orrne   r4, r3, r4\r
67     strneb  r4, [r1,#\offs]\r
68     tsteq   r4, #0x80\r
69     andeq   r4, r4, #0x3f\r
70     streqb  r4, [r1,#\offs]\r
71 .endm\r
72 \r
73 @ TileNormShHP (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: register with helper pattern 0xf, touches r3 high bits\r
74 .macro TileNormShHP\r
75     TilePixelShHP 12, 0         @ #0x0000f000\r
76     TilePixelShHP  8, 1         @ #0x00000f00\r
77     TilePixelShHP  4, 2         @ #0x000000f0\r
78     TilePixelShHP  0, 3         @ #0x0000000f\r
79     TilePixelShHP 28, 4         @ #0xf0000000\r
80     TilePixelShHP 24, 5         @ #0x0f000000\r
81     TilePixelShHP 20, 6         @ #0x00f00000\r
82     TilePixelShHP 16, 7         @ #0x000f0000\r
83 .endm\r
84 \r
85 @ TileFlipShHP (r1=pdest, r2=pixels8, r3=pal) r4: scratch, pat: register with helper pattern 0xf\r
86 .macro TileFlipShHP\r
87     TilePixelShHP 16, 0         @ #0x000f0000\r
88     TilePixelShHP 20, 1         @ #0x00f00000\r
89     TilePixelShHP 24, 2         @ #0x0f000000\r
90     TilePixelShHP 28, 3         @ #0xf0000000\r
91     TilePixelShHP  0, 4         @ #0x0000000f\r
92     TilePixelShHP  4, 5         @ #0x000000f0\r
93     TilePixelShHP  8, 6         @ #0x00000f00\r
94     TilePixelShHP 12, 7         @ #0x0000f000\r
95 .endm\r
96 \r
97 \r
98 @ TileSingleSh (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=sx; r12: helper pattern 0xf\r
99 .macro TileSingleSh\r
100     tst     r0, #1              @ not aligned?\r
101     mov     r7, #0x00c000\r
102     orr     r7, r7, #0xc0\r
103     ldrneb  r4, [r1]\r
104     ldreqh  r4, [r1]\r
105     orr     r4, r4, r7\r
106     strneb  r4, [r1], #1\r
107     streqh  r4, [r1], #2\r
108     ldrh    r4, [r1]\r
109     orr     r4, r4, r7\r
110     strh    r4, [r1], #2\r
111     ldrh    r4, [r1]\r
112     orr     r4, r4, r7\r
113     strh    r4, [r1], #2\r
114     ldrh    r4, [r1]\r
115     orr     r4, r4, r7\r
116     strh    r4, [r1], #2\r
117     ldrneb  r4, [r1]\r
118     orr     r4, r4, r7\r
119     strneb  r4, [r1], #1\r
120 .endm\r
121 \r
122 @ TileSingleHi (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=sx, r12: register with helper pattern 0xf\r
123 .macro TileSingleHi\r
124     tst     r1,  #1              @ not aligned?\r
125     mov     r7,  #0x008000\r
126     orr     r7,  r7, #0x80\r
127     ldrneb  r4,  [r1], #1\r
128     ldreqh  r4,  [r1], #2        @ 1ci\r
129     ldrh    r12, [r1], #2\r
130     bic     r4,  r4,  r7, lsr #1\r
131     orr     r4,  r4,  r7\r
132     strneb  r4,  [r1, #-3]\r
133     streqh  r4,  [r1, #-4]\r
134     ldrh    r4,  [r1], #2\r
135     bic     r12, r12, r7, lsr #1\r
136     orr     r12, r12, r7\r
137     strh    r12, [r1, #-4]\r
138     ldrh    r12, [r1], #2\r
139     bic     r4,  r4,  r7, lsr #1\r
140     orr     r4,  r4,  r7\r
141     strh    r4,  [r1, #-4]\r
142     ldrneb  r4,  [r1]\r
143     bic     r12, r12, r7, lsr #1\r
144     orr     r12, r12, r7\r
145     strh    r12, [r1, #-2]\r
146     bicne   r4,  r4,  r7, lsr #1\r
147     orrne   r4,  r4,  r7\r
148     strneb  r4,  [r1], #1\r
149     mov     r12, #0xf\r
150 .endm\r
151 \r
152 .macro TileDoShGenPixel shift ofs\r
153 .if \shift\r
154     ands    r4, r12, r2, lsr #\shift\r
155 .else\r
156     ands    r4, r12, r2\r
157 .endif\r
158     beq     3f\r
159     cmp     r4, #0xe\r
160     beq     2f\r
161     bgt     1f\r
162     orr     r4, r3, r4\r
163     strb    r4, [r1,#\ofs]\r
164     b       3f\r
165 1:\r
166     ldrb    r4, [r1,#\ofs]        @ 2ci\r
167     orr     r4, r4, #0xc0\r
168     strb    r4, [r1,#\ofs]\r
169     b       3f\r
170 2:\r
171     ldrb    r4, [r1,#\ofs]        @ 2ci\r
172     bic     r4, r4, #0xc0\r
173     orr     r4, r4, #0x80\r
174     strb    r4, [r1,#\ofs]\r
175 3:\r
176 .endm\r
177 \r
178 @ TileFlipSh (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=sx, r12: register with helper pattern 0xf\r
179 .macro TileFlipSh\r
180     TileDoShGenPixel 16,  0 @ #0x000f0000\r
181     TileDoShGenPixel 20,  1 @ #0x00f00000\r
182     TileDoShGenPixel 24,  2 @ #0x0f000000\r
183     TileDoShGenPixel 28,  3 @ #0xf0000000\r
184     TileDoShGenPixel  0,  4 @ #0x0000000f\r
185     TileDoShGenPixel  4,  5 @ #0x000000f0\r
186     TileDoShGenPixel  8,  6 @ #0x00000f00\r
187     TileDoShGenPixel 12,  7 @ #0x0000f000\r
188 .endm\r
189 \r
190 @ TileNormSh (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=sx, r12: register with helper pattern 0xf\r
191 .macro TileNormSh\r
192     TileDoShGenPixel 12,  0 @ #0x0000f000\r
193     TileDoShGenPixel  8,  1 @ #0x00000f00\r
194     TileDoShGenPixel  4,  2 @ #0x000000f0\r
195     TileDoShGenPixel  0,  3 @ #0x0000000f\r
196     TileDoShGenPixel 28,  4 @ #0xf0000000\r
197     TileDoShGenPixel 24,  5 @ #0x0f000000\r
198     TileDoShGenPixel 20,  6 @ #0x00f00000\r
199     TileDoShGenPixel 16,  7 @ #0x000f0000\r
200 .endm\r
201 \r
202 \r
203 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
204 \r
205 @ struct TileStrip\r
206 @ {\r
207 @   int nametab; // 0x00\r
208 @   int line;    // 0x04\r
209 @   int hscroll; // 0x08\r
210 @   int xmask;   // 0x0C\r
211 @   int *hc;     // 0x10 (pointer to cache buffer)\r
212 @   int cells;   // 0x14\r
213 @ };\r
214 \r
215 @ void DrawLayer(int plane_sh, int *hcache, int cellskip, int maxcells);\r
216 \r
217 .global DrawLayer\r
218 \r
219 DrawLayer:\r
220     stmfd   sp!, {r4-r11,lr}\r
221 \r
222     ldr     r11, =(Pico+0x22228)  @ Pico.video\r
223     mov     r8, #1\r
224 \r
225     ldrb    r7, [r11, #16]        @ ??vv??hh\r
226 \r
227     mov     r6, r1                @ hcache\r
228     orr     r9, r3, r0, lsl #30\r
229     orr     r9, r9, r2, lsl #8    @ r9=sh[31]|cellskip[15:8]|maxcells[7:0]  (tmp)\r
230 \r
231     mov     r1, r7, lsl #4\r
232     orr     r1, r1, #0x00ff\r
233 \r
234     and     r10, r7,  #3\r
235     cmp     r10, #1\r
236     biclt   r1,  r1, #0xfc00\r
237     biceq   r1,  r1, #0xfe00\r
238     bicgt   r1,  r1, #0xff00      @ r1=ymask=(height<<8)|0xff; ...; // Y Mask in pixels\r
239 \r
240     add     r10, r10, #5\r
241     cmp     r10, #7\r
242     subge   r10, r10, #1          @ r10=shift[width] (5,6,6,7)\r
243 \r
244     @ calculate xmask:\r
245     mov     r5, r8, lsl r10\r
246     sub     r5, r5, #1            @ r5=xmask\r
247 \r
248     @ Find name table:\r
249     ands    r0,  r0, #1\r
250     ldreqb  r12, [r11, #2]\r
251     ldrneb  r12, [r11, #4]\r
252 \r
253     ldr     r2, =Scanline         @ trying to make good use of pipeline here\r
254     ldr     lr, =(Pico+0x10000)   @ lr=Pico.vram\r
255 \r
256     moveq   r12, r12, lsl #10\r
257     movne   r12, r12, lsl #13\r
258     and     r12, r12, #(7<<13)    @ r12=(ts->nametab<<1) (halfword compliant)\r
259 \r
260     ldrh    r8, [r11, #12]\r
261     ldrb    r7, [r11, #11]\r
262     ldr     r2, [r2]\r
263 \r
264     mov     r4, r8, lsr #8        @ pvid->reg[13]\r
265     mov     r4, r4, lsl #10       @ htab=pvid->reg[13]<<9; (halfwords)\r
266     tst     r7, #2\r
267     addne   r4, r4, r2, lsl #2    @ htab+=Scanline<<1; // Offset by line\r
268     tst     r7, #1\r
269     biceq   r4, r4, #0x1f         @ htab&=~0xf; // Offset by tile\r
270     add     r4, r4, r0, lsl #1    @ htab+=plane\r
271     bic     r4, r4, #0x00ff0000   @ just in case\r
272     ldrh    r3, [lr, r4]          @ r3=hscroll\r
273 \r
274     tst     r7, #4\r
275     bne     .DrawStrip_vsscroll\r
276 \r
277     @ Get vertical scroll value:\r
278     add     r7, lr,  #0x012000\r
279     add     r7, r7,  #0x000180    @ r7=Pico.vsram (Pico+0x22180)\r
280     ldr     r7, [r7]\r
281 \r
282     tst     r8, #2\r
283     tstne   r8, #4\r
284     bne     .DrawStrip_interlace\r
285 \r
286     tst     r0, r0\r
287     movne   r7, r7, lsr #16\r
288 \r
289     @ Find the line in the name table\r
290     add     r2, r2, r7\r
291     and     r2, r2, r1\r
292     mov     r4, r2, lsr #3\r
293     add     r10, r10, #1           @ shift[width]++\r
294     add     r12, r12, r4, lsl r10  @ nametab+=(ts.line>>3)<<shift[width];\r
295 \r
296     @ ldmia   r0, {r1,r2,r3,r5,r6,r9} @ r2=line, r3=ts->hscroll, r5=ts->xmask, r6=ts->hc, r9=ts->cells\r
297 \r
298     and     r10,r2,  #7\r
299     mov     r10,r10, lsl #1 @ r10=ty=(ts->line&7)<<1;\r
300     orr     r10,r10, r9, lsl #24\r
301 \r
302     rsb     r8, r3, #0\r
303     mov     r8, r8, lsr #3  @ r8=tilex=(-ts->hscroll)>>3\r
304 \r
305     sub     r1, r3, #1\r
306     and     r1, r1, #7\r
307     add     r7, r1, #1      @ r7=dx=((ts->hscroll-1)&7)+1\r
308 \r
309     tst     r9, #1<<31\r
310     mov     r3, #0\r
311     orrne   r10,r10, #1<<23 @ r10=(cells<<24|sh<<23|hi_not_empty<<22|had_output<<21|ty)\r
312     movne   r3, #0x40       @ default to shadowed pal on sh mode\r
313 \r
314     cmp     r7, #8\r
315     addne   r10,r10, #0x01000000 @ we will loop cells+1 times if there is scroll\r
316 \r
317     and     r9, r9, #0xff00\r
318     add     r8, r8, r9, lsr #8   @ tilex+=cellskip\r
319     add     r7, r7, r9, lsr #5   @ dx+=cellskip<<3;\r
320     sub     r10,r10,r9, lsl #16  @ cells-=cellskip\r
321 \r
322     @ cache some stuff to avoid mem access\r
323 .if OVERRIDE_HIGHCOL\r
324     ldr     r11,=HighCol\r
325     mov     r0, #0xf\r
326     ldr     r11,[r11]\r
327 .else\r
328     ldr     r11,=HighCol\r
329     mov     r0, #0xf\r
330 .endif\r
331 \r
332     mvn     r9, #0               @ r9=prevcode=-1\r
333     add     r1, r11, r7         @ r1=pdest\r
334 \r
335 \r
336     @ r4 & r7 are scratch in this loop\r
337 .dsloop_subr1:\r
338     sub     r1, r1, #8\r
339 .dsloop: @ 40-41 times\r
340     subs    r10,r10, #0x01000000\r
341     bmi     .dsloop_exit\r
342 \r
343 .dsloop_enter:\r
344     and     r7, r5, r8\r
345     add     r7, lr, r7, lsl #1 @ Pico.vram+((tilex&ts->xmask) as halfwords)\r
346     ldrh    r7, [r7, r12]      @ r7=code (int, but from unsigned, no sign extend)\r
347 \r
348     add     r1, r1, #8\r
349     add     r8, r8, #1\r
350 \r
351     tst     r7, #0x8000\r
352     bne     .DrawStrip_hiprio\r
353 \r
354     cmp     r7, r9\r
355     beq     .DrawStrip_samecode @ we know stuff about this tile already\r
356 \r
357     mov     r9, r7          @ remember code\r
358     orr     r10, r10, #1<<21 @ seen non hi-prio tile\r
359 \r
360     movs    r2, r9, lsl #20 @ if (code&0x1000)\r
361     mov     r2, r2, lsl #1\r
362     add     r2, r2, r10, lsl #17\r
363     mov     r2, r2, lsr #17\r
364     eorcs   r2, r2, #0x0e   @ if (code&0x1000) addr^=0xe;\r
365 \r
366     ldr     r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
367 \r
368     bic     r7, r3, #0x3f\r
369     and     r3, r9, #0x6000\r
370     add     r3, r7, r3, lsr #9 @ r3=pal=((code&0x6000)>>9);\r
371 \r
372 .DrawStrip_samecode:\r
373     tst     r2, r2\r
374     beq     .dsloop              @ tileline blank\r
375 \r
376     cmp     r2, r2, ror #4\r
377     beq     .DrawStrip_SingleColor @ tileline singlecolor \r
378 \r
379     tst     r9, #0x0800\r
380     bne     .DrawStrip_TileFlip\r
381 \r
382     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r0: helper pattern\r
383 .DrawStrip_TileNorm:\r
384     TileNorm r0\r
385     b       .dsloop\r
386 \r
387 .DrawStrip_TileFlip:\r
388     TileFlip r0\r
389     b       .dsloop\r
390 \r
391 .DrawStrip_SingleColor:\r
392     and     r4, r2, #0xf\r
393     orr     r4, r3, r4\r
394     orr     r4, r4, r4, lsl #8\r
395     tst     r1, #1             @ not aligned?\r
396     strneb  r4, [r1], #1\r
397     streqh  r4, [r1], #2\r
398     strh    r4, [r1], #2\r
399     strh    r4, [r1], #2\r
400     strh    r4, [r1], #2\r
401     strneb  r4, [r1], #1       @ have a remaining unaligned pixel?\r
402     b       .dsloop_subr1\r
403 \r
404 .DrawStrip_hiprio_maybempt:\r
405     cmp     r7, r9\r
406     beq     .dsloop         @ must've been empty, otherwise we wouldn't get here\r
407     movs    r2, r7, lsl #20 @ if (code&0x1000)\r
408     mov     r2, r2, lsl #1\r
409     add     r2, r2, r10, lsl #17\r
410     mov     r2, r2, lsr #17\r
411     eorcs   r2, r2, #0x0e   @ if (code&0x1000) addr^=0xe;\r
412     ldr     r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
413     mov     r9, r7          @ remember code\r
414     tst     r2, r2\r
415     beq     .dsloop\r
416     orr     r10, r10, #1<<22\r
417 \r
418 .DrawStrip_hiprio:\r
419     tst     r10, #0x00c00000\r
420     beq     .DrawStrip_hiprio_maybempt\r
421     sub     r0, r1, r11\r
422     orr     r7, r7, r0,  lsl #16\r
423     orr     r7, r7, r10, lsl #25 @ (ty<<25)\r
424     tst     r7, #0x1000\r
425     eorne   r7, r7, #7<<26  @ if(code&0x1000) cval^=7<<26;\r
426     str     r7, [r6], #4    @ cache hi priority tile\r
427     mov     r0, #0xf\r
428     b       .dsloop\r
429 \r
430 .dsloop_exit:\r
431     tst     r10, #1<<21 @ seen non hi-prio tile\r
432     ldreq   r1, =rendstatus\r
433     mov     r0, #0\r
434     ldreq   r2, [r1]\r
435     str     r0, [r6]    @ terminate the cache list\r
436     orreq   r2, r2, #0x40 @ had a layer with all hi-prio tiles\r
437     streq   r2, [r1]\r
438 \r
439     ldmfd   sp!, {r4-r11,lr}\r
440     bx      lr\r
441 \r
442 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
443 \r
444 .DrawStrip_vsscroll:\r
445     rsb     r8, r3, #0\r
446     mov     r8, r8, lsr #3        @ r8=tilex=(-ts->hscroll)>>3\r
447     bic     r8, r8, #0x3fc00000\r
448     orr     r8, r8, r5, lsl #25   @ r8=(xmask[31:25]|had_output[24]|tilex[21:0])\r
449 \r
450     ldr     r4, =Scanline\r
451     orr     r5, r1, r10, lsl #24\r
452     ldr     r4, [r4]\r
453     sub     r1, r3, #1\r
454     orr     r5, r5, r4, lsl #16   @ r5=(shift_width[31:24]|scanline[23:16]|ymask[15:0])\r
455     and     r1, r1, #7\r
456     add     r7, r1, #1            @ r7=dx=((ts->hscroll-1)&7)+1\r
457 \r
458     mov     r10,r9, lsl #16\r
459     tst     r0, #1\r
460     orrne   r10,r10, #0x8000\r
461     tst     r9, #1<<31\r
462     mov     r3, #0\r
463     orr     r10,r10, #0xff000000 @ will be adjusted on entering loop\r
464     orrne   r10,r10, #1<<23 @ r10=(cell[31:24]|sh[23]|hi_not_empty[22]|cells_max[21:16]|plane[15]|ty[14:0])\r
465     movne   r3, #0x40       @ default to shadowed pal on sh mode\r
466 \r
467     cmp     r7, #8\r
468     subne   r10,r10, #0x01000000 @ have hscroll, start with negative cell\r
469 \r
470     and     r9, r9, #0xff00\r
471     add     r8, r8, r9, lsr #8   @ tilex+=cellskip\r
472     add     r7, r7, r9, lsr #5   @ dx+=cellskip<<3;\r
473     add     r10,r10,r9, lsl #16  @ cell+=cellskip\r
474 \r
475     @ cache some stuff to avoid mem access\r
476 .if OVERRIDE_HIGHCOL\r
477     ldr     r11,=HighCol\r
478     mov     r0, #0xf\r
479     ldr     r11,[r11]\r
480 .else\r
481     ldr     r11,=HighCol\r
482     mov     r0, #0xf\r
483 .endif\r
484 \r
485     mvn     r9, #0               @ r9=prevcode=-1\r
486     add     r1, r11, r7          @ r1=pdest\r
487 \r
488     @ r4 & r7 are scratch in this loop\r
489 .dsloop_vs_subr1:\r
490     sub     r1, r1, #8\r
491 .dsloop_vs: @ 40-41 times\r
492     add     r10,r10, #0x01000000\r
493     and     r4, r10, #0x003f0000\r
494     cmp     r4, r10, asr #8\r
495     ble     .dsloop_vs_exit\r
496 \r
497     @ calc offset and read tileline code to r7, also calc ty\r
498     add     r7, lr, #0x012000\r
499     add     r7, r7, #0x000180     @ r7=Pico.vsram (Pico+0x22180)\r
500     add     r7, r7, r10,asr #23   @ vsram + ((cell&~1)<<1)\r
501     bic     r7, r7, #3\r
502     tst     r10,#0x8000           @ plane1?\r
503     addne   r7, r7, #2\r
504     ldrh    r7, [r7]              @ r7=vscroll\r
505 \r
506     bic     r10,r10,#0xff         @ clear old ty\r
507     and     r4, r5, #0xff0000     @ scanline\r
508     add     r4, r4, r7, lsl #16   @ ... += vscroll\r
509     and     r4, r4, r5, lsl #16   @ ... &= ymask\r
510     and     r7, r4, #0x70000\r
511     orr     r10,r10,r7, lsr #15   @ new ty\r
512 \r
513     mov     r4, r4, lsr #19\r
514     mov     r7, r5, lsr #24\r
515     mov     r4, r4, lsl r7        @ nametabadd\r
516 \r
517     and     r7, r8, r8, lsr #25\r
518     add     r7, lr, r7, lsl #1    @ Pico.vram+((tilex&ts->xmask) as halfwords)\r
519     add     r7, r7, r4, lsl #1\r
520     ldrh    r7, [r7, r12]         @ r7=code (int, but from unsigned, no sign extend)\r
521 \r
522     add     r1, r1, #8\r
523     add     r8, r8, #1\r
524 \r
525     tst     r7, #0x8000\r
526     bne     .DrawStrip_vs_hiprio\r
527 \r
528     cmp     r7, r9\r
529     beq     .DrawStrip_vs_samecode @ we know stuff about this tile already\r
530 \r
531     mov     r9, r7          @ remember code\r
532     orr     r8, r8, #(1<<24)@ seen non hi-prio tile\r
533 \r
534     movs    r2, r9, lsl #20 @ if (code&0x1000)\r
535     mov     r2, r2, lsl #1\r
536     add     r2, r2, r10, lsl #17\r
537     mov     r2, r2, lsr #17\r
538     eorcs   r2, r2, #0x0e   @ if (code&0x1000) addr^=0xe;\r
539 \r
540     ldr     r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
541 \r
542     bic     r7, r3, #0x3f\r
543     and     r3, r9, #0x6000\r
544     add     r3, r7, r3, lsr #9 @ r3=pal=((code&0x6000)>>9);\r
545 \r
546 .DrawStrip_vs_samecode:\r
547     tst     r2, r2\r
548     beq     .dsloop_vs              @ tileline blank\r
549 \r
550     cmp     r2, r2, ror #4\r
551     beq     .DrawStrip_vs_SingleColor @ tileline singlecolor \r
552 \r
553     tst     r9, #0x0800\r
554     bne     .DrawStrip_vs_TileFlip\r
555 \r
556     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r0: helper pattern\r
557 .DrawStrip_vs_TileNorm:\r
558     TileNorm r0\r
559     b       .dsloop_vs\r
560 \r
561 .DrawStrip_vs_TileFlip:\r
562     TileFlip r0\r
563     b       .dsloop_vs\r
564 \r
565 .DrawStrip_vs_SingleColor:\r
566     and     r4, r2, #0xf\r
567     orr     r4, r3, r4\r
568     orr     r4, r4, r4, lsl #8\r
569     tst     r1, #1             @ not aligned?\r
570     strneb  r4, [r1], #1\r
571     streqh  r4, [r1], #2\r
572     strh    r4, [r1], #2\r
573     strh    r4, [r1], #2\r
574     strh    r4, [r1], #2\r
575     strneb  r4, [r1], #1       @ have a remaining unaligned pixel?\r
576     b       .dsloop_vs_subr1\r
577 \r
578 .DrawStrip_vs_hiprio:\r
579     tst     r10, #0x00c00000\r
580     beq     .DrawStrip_vs_hiprio_maybempt\r
581     sub     r0, r1, r11\r
582     orr     r7, r7, r0,  lsl #16\r
583     orr     r7, r7, r10, lsl #25 @ (ty<<25)\r
584     tst     r7, #0x1000\r
585     eorne   r7, r7, #7<<26  @ if(code&0x1000) cval^=7<<26;\r
586     str     r7, [r6], #4    @ cache hi priority tile\r
587     mov     r0, #0xf\r
588     b       .dsloop_vs\r
589 \r
590 .DrawStrip_vs_hiprio_maybempt:\r
591     cmp     r7, r9\r
592     beq     .dsloop_vs         @ must've been empty, otherwise we wouldn't get here\r
593     movs    r2, r7, lsl #20 @ if (code&0x1000)\r
594     mov     r2, r2, lsl #1\r
595     add     r2, r2, r10, lsl #17\r
596     mov     r2, r2, lsr #17\r
597     eorcs   r2, r2, #0x0e   @ if (code&0x1000) addr^=0xe;\r
598     ldr     r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
599     mov     r9, r7          @ remember code\r
600     tst     r2, r2\r
601     orrne   r10, r10, #1<<22\r
602     bne     .DrawStrip_vs_hiprio\r
603     b       .dsloop_vs\r
604 \r
605 .dsloop_vs_exit:\r
606     tst     r8, #(1<<24) @ seen non hi-prio tile\r
607     ldreq   r1, =rendstatus\r
608     mov     r0, #0\r
609     ldreq   r2, [r1]\r
610     str     r0, [r6]    @ terminate the cache list\r
611     orreq   r2, r2, #0x40 @ had a layer with all hi-prio tiles\r
612     streq   r2, [r1]\r
613 \r
614     ldmfd   sp!, {r4-r11,lr}\r
615     bx      lr\r
616 \r
617 \r
618 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
619 \r
620 @ interlace mode 2? Sonic 2?\r
621 .DrawStrip_interlace:\r
622     tst     r0, r0\r
623     moveq   r7, r7, lsl #21\r
624     movne   r7, r7, lsl #5\r
625 \r
626     @ Find the line in the name table\r
627     add     r2, r7, r2, lsl #22    @ r2=(vscroll+(Scanline<<1))<<21 (11 bits);\r
628     orr     r1, r1, #0x80000000\r
629     and     r2, r2, r1, ror #10    @ &((ymask<<1)|1)<<21;\r
630     mov     r2, r2, lsr #21\r
631     mov     r4, r2, lsr #4\r
632     mov     r12, r12, lsr #1       @ halfwords\r
633     add     r0, r12, r4, lsl r10   @ nametab+=(ts.line>>4)<<shift[width];\r
634     and     r9, r9, #0xff\r
635 \r
636     sub     sp, sp, #6*4\r
637     stmia   sp, {r0,r2,r3,r5,r6,r9}\r
638 \r
639     mov     r0, sp\r
640     bl      DrawStripInterlace @ struct TileStrip *ts\r
641 \r
642     add     sp, sp, #6*4\r
643     ldmfd   sp!, {r4-r11,lr}\r
644     bx      lr\r
645 \r
646 .pool\r
647 \r
648 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
649 \r
650 \r
651 .global BackFill @ int reg7, int sh\r
652 \r
653 BackFill:\r
654     stmfd   sp!, {r4-r9,lr}\r
655 \r
656 .if OVERRIDE_HIGHCOL\r
657     ldr     lr, =HighCol\r
658     mov     r0, r0, lsl #26\r
659     ldr     lr, [lr]\r
660     mov     r0, r0, lsr #26\r
661     add     lr, lr, #8\r
662 .else\r
663     ldr     lr, =(HighCol+8)\r
664     mov     r0, r0, lsl #26\r
665     mov     r0, r0, lsr #26\r
666 .endif\r
667 \r
668     orr     r0, r0, r1, lsl #6\r
669     orr     r0, r0, r0, lsl #8\r
670     orr     r0, r0, r0, lsl #16\r
671 \r
672     mov     r1, r0\r
673     mov     r2, r0\r
674     mov     r3, r0\r
675     mov     r4, r0\r
676     mov     r5, r0\r
677     mov     r6, r0\r
678     mov     r7, r0\r
679 \r
680     @ go go go!\r
681     stmia   lr!, {r0-r7} @ 10*8*4\r
682     stmia   lr!, {r0-r7}\r
683     stmia   lr!, {r0-r7}\r
684     stmia   lr!, {r0-r7}\r
685     stmia   lr!, {r0-r7}\r
686     stmia   lr!, {r0-r7}\r
687     stmia   lr!, {r0-r7}\r
688     stmia   lr!, {r0-r7}\r
689     stmia   lr!, {r0-r7}\r
690     stmia   lr!, {r0-r7}\r
691 \r
692     ldmfd   sp!, {r4-r9,r12}\r
693     bx      r12\r
694 \r
695 \r
696 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
697 \r
698 \r
699 .global DrawTilesFromCache @ int *hc, int sh, int rlim\r
700 \r
701 DrawTilesFromCache:\r
702     stmfd   sp!, {r4-r8,r11,lr}\r
703 \r
704     @ cache some stuff to avoid mem access\r
705 .if OVERRIDE_HIGHCOL\r
706     ldr     r11,=HighCol\r
707     mov     r12,#0xf\r
708     ldr     r11,[r11]\r
709 .else\r
710     ldr     r11,=HighCol\r
711     mov     r12,#0xf\r
712 .endif\r
713     ldr     lr, =(Pico+0x10000) @ lr=Pico.vram\r
714 \r
715     mvn     r5, #0         @ r5=prevcode=-1\r
716     ands    r8, r1, #1\r
717     orr     r8, r8, r2, lsl #1\r
718     bne     .dtfc_check_rendflags\r
719 \r
720     @ scratch: r4, r7\r
721 .dtfc_loop:\r
722     ldr     r6, [r0], #4    @ read code\r
723     movs    r1, r6, lsr #16 @ r1=dx;\r
724     ldmeqfd sp!, {r4-r8,r11,pc} @ dx is never zero, this must be a terminator, return\r
725     bic     r4, r1, #0xfe00\r
726     add     r1, r11, r4     @ r1=pdest\r
727 \r
728     mov     r7, r6, lsl #16\r
729     cmp     r5, r7, lsr #16\r
730     beq     .dtfc_samecode  @ if (code==prevcode)\r
731 \r
732     mov     r5, r7, lsr #16\r
733 \r
734     mov     r2, r5, lsl #21\r
735     mov     r2, r2, lsr #17 @ r2=addr=(code&0x7ff)<<4;\r
736     add     r2, r2, r6, lsr #25 @ addr+=ty\r
737 \r
738     and     r3, r5, #0x6000\r
739     mov     r3, r3, lsr #9  @ r3=pal=((code&0x6000)>>9);\r
740 \r
741     ldr     r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
742 \r
743 .dtfc_samecode:\r
744     rsbs    r4, r4, r8, lsr #1\r
745     bmi     .dtfc_cut_tile\r
746 \r
747     tst     r8, #1\r
748     bne     .dtfc_shadow\r
749 \r
750     tst     r2, r2\r
751     beq     .dtfc_loop\r
752 \r
753     cmp     r2, r2, ror #4\r
754     beq     .dtfc_SingleColor @ tileline singlecolor \r
755 \r
756     tst     r5, #0x0800\r
757     bne     .dtfc_TileFlip\r
758 \r
759     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
760 .dtfc_TileNorm:\r
761     TileNorm r12\r
762     b       .dtfc_loop\r
763 \r
764 .dtfc_TileFlip:\r
765     TileFlip r12\r
766     b       .dtfc_loop\r
767 \r
768 .dtfc_SingleColor:\r
769     and     r4, r2, #0xf\r
770     orr     r4, r3, r4\r
771     orr     r4, r4, r4, lsl #8\r
772     tst     r1, #1              @ not aligned?\r
773     strneb  r4, [r1], #1\r
774     streqh  r4, [r1], #2\r
775     strh    r4, [r1], #2\r
776     strh    r4, [r1], #2\r
777     strh    r4, [r1], #2\r
778     strneb  r4, [r1], #1        @ have a remaining unaligned pixel?\r
779     b       .dtfc_loop\r
780 \r
781 .dtfc_shadow:\r
782     tst     r2, r2\r
783     beq     .dtfc_shadow_blank\r
784 \r
785     cmp     r2, r2, ror #4\r
786     beq     .dtfc_SingleColor @ tileline singlecolor \r
787 \r
788     tst     r5, #0x0800\r
789     bne     .dtfc_TileFlipShHP\r
790 \r
791     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
792 .dtfc_TileNormShHP:\r
793     TileNormShHP\r
794     b       .dtfc_loop\r
795 \r
796 .dtfc_TileFlipShHP:\r
797     TileFlipShHP\r
798     b       .dtfc_loop\r
799 \r
800 .dtfc_shadow_blank:\r
801     ldrb    r4, [r1]        @ 1ci\r
802     ldrb    r12,[r1,#1]\r
803     tst     r4, #0x80\r
804     andeq   r4, r4,#0x3f\r
805     streqb  r4, [r1]\r
806     tst     r12,#0x80\r
807     ldrb    r4, [r1,#2]\r
808     andeq   r12,r12,#0x3f\r
809     streqb  r12,[r1,#1]\r
810     tst     r4, #0x80\r
811     ldrb    r12,[r1,#3]\r
812     andeq   r4, r4,#0x3f\r
813     streqb  r4, [r1,#2]\r
814     tst     r12,#0x80\r
815     ldrb    r4, [r1,#4]\r
816     andeq   r12,r12,#0x3f\r
817     streqb  r12,[r1,#3]\r
818     tst     r4, #0x80\r
819     ldrb    r12,[r1,#5]\r
820     andeq   r4, r4,#0x3f\r
821     streqb  r4, [r1,#4]\r
822     tst     r12,#0x80\r
823     ldrb    r4, [r1,#6]\r
824     andeq   r12,r12,#0x3f\r
825     streqb  r12,[r1,#5]\r
826     tst     r4, #0x80\r
827     ldrb    r12,[r1,#7]\r
828     andeq   r4, r4,#0x3f\r
829     streqb  r4, [r1,#6]\r
830     tst     r12,#0x80\r
831     andeq   r12,r12,#0x3f\r
832     streqb  r12,[r1,#7]\r
833     mov     r12, #0xf\r
834     b       .dtfc_loop\r
835 \r
836 .dtfc_cut_tile:\r
837     add     r4, r4, #7      @ 0-6\r
838     mov     r4, r4, lsl #2\r
839     mov     r12,#0xf<<28\r
840     mov     r12,r12,asr r4\r
841     mov     r2, r2, ror #16\r
842     tst     r5, #0x0800     @ flipped?\r
843     mvnne   r12,r12\r
844     and     r2, r2, r12\r
845     mov     r2, r2, ror #16\r
846     mov     r12,#0xf\r
847     tst     r8, #1\r
848     bne     .dtfc_shadow\r
849     tst     r2, r2\r
850     beq     .dtfc_loop\r
851     tst     r5, #0x0800\r
852     beq     .dtfc_TileNorm\r
853     b       .dtfc_TileFlip\r
854 \r
855 @ check if we have detected layer covered with hi-prio tiles:\r
856 .dtfc_check_rendflags:\r
857     ldr     r1, =rendstatus\r
858     ldr     r2, [r1]\r
859     tst     r2, #0xc0\r
860     beq     .dtfc_loop\r
861     bic     r8, r8, #1      @ sh/hi mode off\r
862     tst     r2, #0x80\r
863     bne     .dtfc_loop      @ already processed\r
864     orr     r2, r2, #0x80\r
865     str     r2, [r1]\r
866 \r
867     add     r1, r11,#8\r
868     mov     r3, #320/4\r
869     mov     r7, #0x80\r
870     orr     r7, r7, r7, lsl #8\r
871     orr     r7, r7, r7, lsl #16\r
872     mov     r6, #0x3f\r
873     orr     r6, r6, r6, lsl #8\r
874     orr     r6, r6, r6, lsl #16\r
875 .dtfc_loop_shprep:\r
876     subs    r3, r3, #1\r
877     bmi     .dtfc_loop      @ done\r
878     ldr     r2, [r1]\r
879     tst     r2, r7\r
880     andeq   r2, r2, r6\r
881     streq   r2, [r1], #4\r
882     beq     .dtfc_loop_shprep\r
883     tst     r2,     #0x80000000\r
884     biceq   r2, r2, #0xc0000000\r
885     tst     r2,     #0x00800000\r
886     biceq   r2, r2, #0x00c00000\r
887     tst     r2,     #0x00008000\r
888     biceq   r2, r2, #0x0000c000\r
889     tst     r2,     #0x00000080\r
890     biceq   r2, r2, #0x000000c0\r
891     str     r2, [r1], #4\r
892     b       .dtfc_loop_shprep\r
893 \r
894 .pool\r
895 \r
896 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
897 \r
898 \r
899 .global DrawSpritesFromCache @ int *hc, int maxwidth, int prio, int sh\r
900 \r
901 DrawSpritesFromCache:\r
902     stmfd   sp!, {r4-r11,lr}\r
903 \r
904     @ cache some stuff to avoid mem access\r
905 .if OVERRIDE_HIGHCOL\r
906     ldr     r11,=HighCol\r
907     mov     r12,#0xf\r
908     ldr     r11,[r11]\r
909 .else\r
910     ldr     r11,=HighCol\r
911     mov     r12,#0xf\r
912 .endif\r
913     ldr     lr, =(Pico+0x10000) @ lr=Pico.vram\r
914     mov     r6, r3, lsl #31\r
915     orr     r6, r6, #1<<30\r
916 \r
917     mov     r10, r0\r
918 \r
919 .dsfc_loop:\r
920     ldr     r9, [r10], #4    @ read code\r
921     bic     r6, r6, #7       @ using pipeline\r
922     tst     r9, r9\r
923     ldmeqfd sp!, {r4-r11,pc}\r
924 \r
925     mov     r4, r9, lsl #28\r
926     orr     r6, r6, r4, lsr #30\r
927     add     r6, r6, #1       @ r6=s1cc???? ... ?????www (s=shadow/hilight, cc=pal, w=width)\r
928 \r
929     and     r5, r9, #3\r
930     add     r5, r5, #1       @ r5=delta\r
931     tst     r9, #0x10000\r
932     rsbne   r5, r5, #0       @ Flip X\r
933     mov     r5, r5, lsl #4\r
934 \r
935     mov     r2, r9, lsr #17\r
936     mov     r8, r2, lsl #1   @ tile=((unsigned int)code>>17)<<1;\r
937 \r
938     and     r3, r9, #0x30    @ r3=pal=(code&0x30);\r
939 \r
940     bic     r6, r6, #3<<28\r
941     orr     r6, r6, r3, lsl #24\r
942 \r
943     mov     r0, r9, lsl #16\r
944     mov     r0, r0, asr #22  @ sx=(code<<16)>>22\r
945     adds    r0, r0, #0       @ set ZV\r
946     b       .dsfc_inloop_enter\r
947 \r
948 @ scratch: r4, r7\r
949 .dsfc_inloop:\r
950     sub     r6, r6, #1\r
951     tst     r6, #7\r
952     beq     .dsfc_loop\r
953     adds    r0, r0, #8\r
954     add     r8, r8, r5\r
955 \r
956 .dsfc_inloop_enter:\r
957     ble     .dsfc_inloop\r
958     cmp     r0, #328\r
959     bge     .dsfc_loop\r
960 \r
961     mov     r8, r8, lsl #17\r
962     mov     r8, r8, lsr #17   @ tile&=0x7fff; // Clip tile address\r
963 \r
964     ldr     r2, [lr, r8, lsl #1] @ pack=*(unsigned int *)(Pico.vram+tile); // Get 8 pixels\r
965     add     r1, r11, r0       @ r1=pdest\r
966     tst     r2, r2\r
967     beq     .dsfc_inloop\r
968 \r
969     cmp     r12, r6, lsr #28\r
970     beq     .dsfc_shadow\r
971 \r
972     cmp     r2, r2, ror #4\r
973     beq     .dsfc_SingleColor @ tileline singlecolor \r
974 \r
975     tst     r9, #0x10000\r
976     bne     .dsfc_TileFlip\r
977 \r
978     @ TileFlip (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
979 .dsfc_TileNorm:\r
980     TileNorm r12\r
981     b       .dsfc_inloop\r
982 \r
983 .dsfc_TileFlip:\r
984     TileFlip r12\r
985     b       .dsfc_inloop\r
986 \r
987 .dsfc_SingleColor:\r
988     tst     r0, #1              @ not aligned?\r
989     and     r4, r2, #0xf\r
990     orr     r4, r3, r4\r
991     orr     r4, r4, r4, lsl #8\r
992     strneb  r4, [r1], #1\r
993     streqh  r4, [r1], #2\r
994     strh    r4, [r1], #2\r
995     strh    r4, [r1], #2\r
996     strh    r4, [r1], #2\r
997     strneb  r4, [r1], #1\r
998     b       .dsfc_inloop\r
999 \r
1000 .dsfc_shadow:\r
1001     cmp     r2, r2, ror #4\r
1002     beq     .dsfc_singlec_sh\r
1003 \r
1004     tst     r9, #0x10000\r
1005     bne     .dsfc_TileFlip_sh\r
1006 \r
1007     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
1008 .dsfc_TileNorm_sh:\r
1009     TileNormSh\r
1010     b       .dsfc_inloop\r
1011 \r
1012 .dsfc_TileFlip_sh:\r
1013     TileFlipSh\r
1014     b       .dsfc_inloop\r
1015 \r
1016 .dsfc_singlec_sh:\r
1017     cmp     r2, #0xe0000000\r
1018     bcc     .dsfc_SingleColor   @ normal singlecolor tileline (carry inverted in ARM)\r
1019     tst     r2, #0x10000000\r
1020     bne     .dsfc_sh_sh\r
1021     TileSingleHi\r
1022     b       .dsfc_inloop\r
1023 \r
1024 .dsfc_sh_sh:\r
1025     TileSingleSh\r
1026     b       .dsfc_inloop\r
1027 \r
1028 .pool\r
1029 \r
1030 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
1031 \r
1032 @ + 0  :    hhhhvvvv ab--hhvv yyyyyyyy yyyyyyyy // a: offscreen h, b: offs. v, h: horiz. size\r
1033 @ + 4  :    xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8\r
1034 \r
1035 .global DrawSprite @ unsigned int *sprite, int **hc, int sh, int acc_sprites\r
1036 \r
1037 DrawSprite:\r
1038     stmfd   sp!, {r4-r9,r11,lr}\r
1039 \r
1040     orr     r8, r3, r2, lsl #4\r
1041     ldr     r3, [r0]        @ sprite[0]\r
1042     ldr     r7, =Scanline\r
1043     mov     r6, r3, lsr #28\r
1044     sub     r6, r6, #1      @ r6=width-1 (inc later)\r
1045     mov     r5, r3, lsr #24\r
1046     and     r5, r5, #7      @ r5=height\r
1047 \r
1048     mov     r4, r3, lsl #16 @ r4=sy<<16 (tmp)\r
1049 \r
1050     ldr     r7, [r7]\r
1051     ldr     r9, [r0, #4]\r
1052     sub     r7, r7, r4, asr #16 @ r7=row=Scanline-sy\r
1053 \r
1054     mov     r2, r9, asr #16 @ r2=sx\r
1055     mov     r9, r9, lsl #16\r
1056     mov     r9, r9, lsr #16\r
1057     orr     r9, r9, r8, lsl #27 @ r9=code|sh[31]|as[27]\r
1058 \r
1059     tst     r9, #0x1000\r
1060     movne   r4, r5, lsl #3\r
1061     subne   r4, r4, #1\r
1062     subne   r7, r4, r7      @ if (code&0x1000) row=(height<<3)-1-row; // Flip Y\r
1063 \r
1064     mov     r8, r9, lsl #21\r
1065     mov     r8, r8, lsr #21\r
1066     add     r8, r8, r7, lsr #3 @ tile+=row>>3; // Tile number increases going down\r
1067     \r
1068     tst     r9, #0x0800\r
1069     mlane   r8, r5, r6, r8  @ if (code&0x0800) { tile+=delta*(width-1);\r
1070     rsbne   r5, r5, #0      @ delta=-delta; } // r5=delta now\r
1071 \r
1072     mov     r8, r8, lsl #4\r
1073     and     r7, r7, #7\r
1074     add     r8, r8, r7, lsl #1 @ tile+=(row&7)<<1; // Tile address\r
1075 \r
1076     tst     r9, #0x8000\r
1077     bne     .dspr_cache       @ if(code&0x8000) // high priority - cache it\r
1078 \r
1079 .dspr_continue:\r
1080     @ cache some stuff to avoid mem access\r
1081 .if OVERRIDE_HIGHCOL\r
1082     ldr     r11,=HighCol\r
1083     mov     r12,#0xf\r
1084     ldr     r11,[r11]\r
1085 .else\r
1086     ldr     r11,=HighCol\r
1087     mov     r12,#0xf\r
1088 .endif\r
1089     ldr     lr, =(Pico+0x10000) @ lr=Pico.vram\r
1090 \r
1091     mov     r5, r5, lsl #4     @ delta<<=4; // Delta of address\r
1092     and     r4, r9, #0x6000\r
1093     orr     r9, r9, r4, lsl #16\r
1094     orrs    r9, r9, #0x10000000 @ r9=scc1 a??? ... <code> (s=shadow/hilight, cc=pal, a=acc_spr)\r
1095 \r
1096     mov     r3, r4, lsr #9     @ r3=pal=((code>>9)&0x30);\r
1097     orrmi   r3, r3, #0x40      @ shadow by default\r
1098 \r
1099     add     r6, r6, #1         @ inc now\r
1100     adds    r0, r2, #0         @ mov sx to r0 and set ZV flags\r
1101     b       .dspr_loop_enter\r
1102 \r
1103 .dspr_loop:\r
1104     subs    r6, r6, #1         @ width--\r
1105     ldmeqfd sp!, {r4-r9,r11,pc}@ return\r
1106     adds    r0, r0, #8         @ sx+=8\r
1107     add     r8, r8, r5         @ tile+=delta\r
1108 \r
1109 .dspr_loop_enter:\r
1110     ble     .dspr_loop         @ sx <= 0\r
1111     cmp     r0, #328\r
1112     ldmgefd sp!, {r4-r9,r11,pc}@ return\r
1113 \r
1114     mov     r8, r8, lsl #17\r
1115     mov     r8, r8, lsr #17    @ tile&=0x7fff; // Clip tile address\r
1116 \r
1117     ldr     r2, [lr, r8, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
1118     add     r1, r11, r0        @ r1=pdest\r
1119     tst     r2, r2\r
1120     beq     .dspr_loop\r
1121 \r
1122     cmp     r12, r9, lsr #28\r
1123     beq     .dspr_shadow\r
1124 \r
1125     cmp     r2, r2, ror #4\r
1126     beq     .dspr_SingleColor @ tileline singlecolor \r
1127 \r
1128     tst     r9, #0x0800\r
1129     bne     .dspr_TileFlip\r
1130 \r
1131     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
1132 @ scratch: r4, r7\r
1133 .dspr_TileNorm:\r
1134     TileNorm r12\r
1135     b       .dspr_loop\r
1136 \r
1137 .dspr_TileFlip:\r
1138     TileFlip r12\r
1139     b       .dspr_loop\r
1140 \r
1141 .dspr_SingleColor:\r
1142     and     r4, r2, #0xf\r
1143     orr     r4, r3, r4\r
1144     orr     r4, r4, r4, lsl #8\r
1145     tst     r0, #1              @ not aligned?\r
1146     strneb  r4, [r1], #1\r
1147     streqh  r4, [r1], #2\r
1148     strh    r4, [r1], #2\r
1149     strh    r4, [r1], #2\r
1150     strh    r4, [r1], #2\r
1151     strneb  r4, [r1], #1\r
1152     b       .dspr_loop\r
1153 \r
1154 .dspr_shadow:\r
1155     cmp     r2, r2, ror #4\r
1156     beq     .dspr_singlec_sh\r
1157 \r
1158     tst     r9, #0x0800\r
1159     bne     .dspr_TileFlip_sh\r
1160 \r
1161     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
1162 .dspr_TileNorm_sh:\r
1163     TileNormSh\r
1164     b       .dspr_loop\r
1165 \r
1166 .dspr_TileFlip_sh:\r
1167     TileFlipSh\r
1168     b       .dspr_loop\r
1169 \r
1170 .dspr_singlec_sh:\r
1171     cmp     r2, #0xe0000000\r
1172     bcc     .dspr_SingleColor   @ normal tileline\r
1173     tst     r2, #0x10000000\r
1174     bne     .dspr_sh_sh\r
1175     TileSingleHi\r
1176     b       .dspr_loop\r
1177 \r
1178 .dspr_sh_sh:\r
1179     TileSingleSh\r
1180     b       .dspr_loop\r
1181 \r
1182 \r
1183 .dspr_cache:\r
1184     @ *(*hc)++ = (tile<<16)|((code&0x0800)<<5)|((sx<<6)&0x0000ffc0)|((code>>9)&0x30)|((sprite[0]>>24)&0xf);\r
1185     mov     r4, r8, lsl #16     @ tile\r
1186     tst     r9, #0x0800\r
1187     orrne   r4, r4, #0x10000    @ code&0x0800\r
1188     mov     r0, r2, lsl #22\r
1189     orr     r4, r4, r0, lsr #16 @ (sx<<6)&0x0000ffc0\r
1190     and     r0, r9, #0x6000\r
1191     orr     r4, r4, r0, lsr #9  @ (code>>9)&0x30\r
1192     mov     r3, r3, lsl #12\r
1193     ldr     r0, [r1]\r
1194     orr     r4, r4, r3, lsr #28 @ (sprite[0]>>24)&0xf\r
1195 \r
1196     str     r4, [r0], #4\r
1197     str     r0, [r1]\r
1198 \r
1199     tst     r9, #(1<<27)\r
1200     ldmeqfd sp!, {r4-r9,r11,lr}\r
1201     bne     .dspr_continue      @ draw anyway if accurate sprites enabled\r
1202     bxeq    lr\r
1203 \r
1204 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
1205 \r
1206 .global DrawWindow @ int tstart, int tend, int prio, int sh // int *hcache\r
1207 \r
1208 DrawWindow:\r
1209     stmfd   sp!, {r4-r11,lr}\r
1210 \r
1211     ldr     r11, =(Pico+0x22228)  @ Pico.video\r
1212     ldr     r10, =Scanline\r
1213     ldrb    r12, [r11, #3]        @ pvid->reg[3]\r
1214 \r
1215     ldr     r10, [r10]\r
1216     ldr     r4,  [r11, #12]\r
1217     mov     r5,  r10, lsr #3\r
1218     and     r10, r10, #7\r
1219     mov     r10, r10, lsl #1      @ r10=ty\r
1220 \r
1221     mov     r12, r12, lsl #10\r
1222 \r
1223     tst     r4, #1                @ 40 cell mode?\r
1224     andne   r12, r12, #0xf000     @ 0x3c<<10\r
1225     andeq   r12, r12, #0xf800\r
1226     addne   r12, r12, r5, lsl #7\r
1227     addeq   r12, r12, r5, lsl #6  @ nametab\r
1228     add     r12, r12, r0, lsl #2  @ +starttile\r
1229 \r
1230     ldr     r6, =rendstatus\r
1231     ldr     lr, =(Pico+0x10000) @ lr=Pico.vram\r
1232     ldrb    r6, [r6]\r
1233 \r
1234     @ fetch the first code now\r
1235     ldrh    r7, [lr, r12]\r
1236 \r
1237     ands    r6, r6, #2            @ we care about bit 1 only\r
1238     orr     r6, r6, r2\r
1239     bne     .dw_no_sameprio\r
1240 \r
1241     cmp     r2, r7, lsr #15\r
1242     ldmnefd sp!, {r4-r11,pc}      @ assume that whole window uses same priority\r
1243 \r
1244 .dw_no_sameprio:\r
1245     orr     r6, r6, r3, lsl #8    @ shadow mode\r
1246 \r
1247     sub     r8, r1, r0\r
1248 \r
1249     @ cache some stuff to avoid mem access\r
1250 .if OVERRIDE_HIGHCOL\r
1251     ldr     r11,=HighCol\r
1252     mov     r8, r8, lsl #1        @ cells\r
1253     ldr     r11,[r11]\r
1254     mvn     r9, #0                @ r9=prevcode=-1\r
1255     add     r11,r11,#8\r
1256 .else\r
1257     ldr     r11,=(HighCol+8)\r
1258     mov     r8, r8, lsl #1        @ cells\r
1259     mvn     r9, #0                @ r9=prevcode=-1\r
1260 .endif\r
1261     add     r1, r11, r0, lsl #4 @ r1=pdest\r
1262     mov     r0, #0xf\r
1263     b       .dwloop_enter\r
1264 \r
1265     @ r4,r5 & r7 are scratch in this loop\r
1266 .dwloop:\r
1267     add     r1, r1, #8\r
1268 .dwloop_nor1:\r
1269     add     r12, r12, #2    @ halfwords\r
1270     ldrh    r7, [lr, r12]   @ r7=code (int, but from unsigned, no sign extend)\r
1271     subs    r8, r8, #1\r
1272     beq     .dwloop_end     @ done\r
1273 \r
1274     eor     r5, r6, r7, lsr #15\r
1275     tst     r5, #1\r
1276     orrne   r6, r6, #2      @ wrong pri\r
1277     bne     .dwloop\r
1278 \r
1279     cmp     r7, r9\r
1280     beq     .dw_samecode    @ we know stuff about this tile already\r
1281 \r
1282 .dwloop_enter:\r
1283     mov     r9, r7          @ remember code\r
1284 \r
1285     movs    r2, r9, lsl #20 @ if (code&0x1000)\r
1286     mov     r2, r2, lsl #1\r
1287     add     r2, r10, r2, lsr #17 @ r2=addr=(code&0x7ff)<<4; addr+=ty\r
1288     eorcs   r2, r2, #0x0e   @ if (code&0x1000) addr^=0xe;\r
1289 \r
1290     and     r3, r9, #0x6000\r
1291     mov     r3, r3, lsr #9  @ r3=pal=((code&0x6000)>>9);\r
1292 \r
1293     ldr     r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
1294 \r
1295 .dw_samecode:\r
1296     tst     r6, #0x100\r
1297     bne     .dw_shadow\r
1298 .dw_shadow_done:\r
1299     tst     r2, r2\r
1300     beq     .dwloop              @ tileline blank\r
1301 \r
1302     cmp     r2, r2, ror #4\r
1303     beq     .dw_SingleColor @ tileline singlecolor \r
1304 \r
1305     tst     r9, #0x0800\r
1306     bne     .dw_TileFlip\r
1307 \r
1308     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r0: helper pattern\r
1309 .dw_TileNorm:\r
1310     TileNorm r0\r
1311     b       .dwloop\r
1312 \r
1313 .dw_TileFlip:\r
1314     TileFlip r0\r
1315     b       .dwloop\r
1316 \r
1317 .dw_SingleColor:\r
1318     and     r4, r0, r2         @ #0x0000000f\r
1319     orr     r4, r3, r4\r
1320     orr     r4, r4, r4, lsl #8\r
1321     orr     r4, r4, r4, lsl #16\r
1322     mov     r5, r4\r
1323     stmia   r1!, {r4,r5}\r
1324     b       .dwloop_nor1       @ we incremeted r1 ourselves\r
1325 \r
1326 .dw_shadow:\r
1327     tst     r6, #1             @ hi pri?\r
1328     orreq   r3, r3, #0x40\r
1329     beq     .dw_shadow_done\r
1330     ldr     r4, [r1]\r
1331     tst     r4, #0x00000080\r
1332     biceq   r4, r4, #0x000000c0\r
1333     tst     r4, #0x00008000\r
1334     biceq   r4, r4, #0x0000c000\r
1335     tst     r4, #0x00800000\r
1336     biceq   r4, r4, #0x00c00000\r
1337     tst     r4, #0x80000000\r
1338     biceq   r4, r4, #0xc0000000\r
1339     str     r4, [r1]\r
1340     ldr     r4, [r1,#4]\r
1341     tst     r4, #0x00000080\r
1342     biceq   r4, r4, #0x000000c0\r
1343     tst     r4, #0x00008000\r
1344     biceq   r4, r4, #0x0000c000\r
1345     tst     r4, #0x00800000\r
1346     biceq   r4, r4, #0x00c00000\r
1347     tst     r4, #0x80000000\r
1348     biceq   r4, r4, #0xc0000000\r
1349     str     r4, [r1,#4]\r
1350     b       .dw_shadow_done\r
1351 \r
1352 .dwloop_end:\r
1353     ldr     r0, =rendstatus\r
1354     ldr     r1, [r0]\r
1355     and     r6, r6, #2\r
1356     orr     r1, r1, r6\r
1357     str     r1, [r0]\r
1358 \r
1359     ldmfd   sp!, {r4-r11,r12}\r
1360     bx      r12\r
1361 \r
1362 \r
1363 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
1364 \r
1365 \r
1366 @ hilights 2 pixels in RGB444/BGR444 format\r
1367 .macro TileDoShHi2Pixels444 reg\r
1368     mov     \reg, \reg, ror #12\r
1369     adds    \reg, \reg, #0x40000000\r
1370     orrcs   \reg, \reg, #0xf0000000\r
1371     mov     \reg, \reg, ror #28\r
1372     adds    \reg, \reg, #0x40000000\r
1373     orrcs   \reg, \reg, #0xf0000000\r
1374     mov     \reg, \reg, ror #28\r
1375     adds    \reg, \reg, #0x40000000\r
1376     orrcs   \reg, \reg, #0xf0000000\r
1377     mov     \reg, \reg, ror #24\r
1378     adds    \reg, \reg, #0x40000000\r
1379     orrcs   \reg, \reg, #0xf0000000\r
1380     mov     \reg, \reg, ror #28\r
1381     adds    \reg, \reg, #0x40000000\r
1382     orrcs   \reg, \reg, #0xf0000000\r
1383     mov     \reg, \reg, ror #28\r
1384     adds    \reg, \reg, #0x40000000\r
1385     orrcs   \reg, \reg, #0xf0000000\r
1386     mov     \reg, \reg, ror #12\r
1387 .endm\r
1388 \r
1389 \r
1390 .global FinalizeLineBGR444 @ int sh\r
1391 \r
1392 FinalizeLineBGR444:\r
1393     stmfd   sp!, {r4-r6,lr}\r
1394     mov     r6, r0\r
1395     ldr     lr, =(Pico+0x22228)  @ Pico.video\r
1396     ldr     r0, =DrawLineDest\r
1397     ldrb    r12, [lr, #12]\r
1398     ldr     r0, [r0]\r
1399     sub     r3, lr, #0x128       @ r3=Pico.cram\r
1400 \r
1401     tst     r12, #1\r
1402     movne   r2, #320/4           @ len\r
1403     bne     .fl_no32colBGR444\r
1404     ldr     r4, =PicoOpt\r
1405     mov     r2, #256/4\r
1406     ldr     r4, [r4]\r
1407     tst     r4, #0x100\r
1408     addeq   r0, r0, #32*2\r
1409 \r
1410 .fl_no32colBGR444:\r
1411     tst     r6, r6\r
1412     beq     .fl_noshBGR444\r
1413 \r
1414     ldr     r4, =HighPal\r
1415 \r
1416     ldrb    r12, [lr, #-0x1a]      @ 0x2220e ~ dirtyPal\r
1417     tst     r12, r12\r
1418     moveq   r3, r4\r
1419     beq     .fl_noshBGR444\r
1420     mov     r12, #0\r
1421     strb    r12, [lr, #-0x1a]\r
1422 \r
1423     mov     lr, #0x40/8\r
1424     @ copy pal:\r
1425 .fl_loopcpBGR444:\r
1426     ldmia   r3!, {r1,r5,r6,r12}\r
1427     subs    lr, lr, #1\r
1428     stmia   r4!, {r1,r5,r6,r12}\r
1429     bne     .fl_loopcpBGR444\r
1430 \r
1431     @ shadowed pixels:\r
1432     mov     r12,    #0x0077\r
1433     orr     r12,r12,#0x0700\r
1434     orr     r12,r12,r12,lsl #16\r
1435     sub     r3, r3, #0x40*2\r
1436     add     r5, r4, #0x80*2\r
1437     mov     lr, #0x40/4\r
1438 .fl_loopcpBGR444_sh:\r
1439     ldmia   r3!, {r1,r6}\r
1440     subs    lr, lr, #1\r
1441     and     r1, r12, r1, lsr #1\r
1442     and     r6, r12, r6, lsr #1\r
1443     stmia   r4!, {r1,r6}\r
1444     stmia   r5!, {r1,r6}\r
1445     bne     .fl_loopcpBGR444_sh\r
1446 \r
1447     @ hilighted pixels:\r
1448     sub     r3, r3, #0x40*2\r
1449     mov     lr, #0x40/2\r
1450 .fl_loopcpBGR444_hi:\r
1451     ldr     r1, [r3], #4\r
1452     TileDoShHi2Pixels444 r1\r
1453     str     r1, [r4], #4\r
1454     subs    lr, lr, #1\r
1455     bne     .fl_loopcpBGR444_hi\r
1456 \r
1457     sub     r3, r4, #0x40*3*2\r
1458     mov     r6, #1\r
1459 \r
1460 \r
1461 .fl_noshBGR444:\r
1462     ldr     r12,=rendstatus\r
1463     eors    r6, r6, #1          @ sh is 0\r
1464     ldr     r12,[r12]\r
1465     mov     lr, #0xff\r
1466     tstne   r12,#(1<<2)         @ and PDRAW_ACC_SPRITES\r
1467 \r
1468 .if OVERRIDE_HIGHCOL\r
1469     ldr     r1, =HighCol\r
1470     movne   lr, #0x3f\r
1471     ldr     r1, [r1]\r
1472     mov     lr, lr, lsl #1\r
1473     add     r1, r1, #8\r
1474 .else\r
1475     ldr     r1, =(HighCol+8)\r
1476     movne   lr, #0x3f\r
1477     mov     lr, lr, lsl #1\r
1478 .endif\r
1479 \r
1480 .fl_loopBGR444:\r
1481     ldr     r12, [r1], #4\r
1482     subs    r2, r2, #1\r
1483 \r
1484     and     r4, lr, r12, lsl #1\r
1485     ldrh    r4, [r3, r4]\r
1486     and     r5, lr, r12, lsr #7\r
1487     ldrh    r5, [r3, r5]\r
1488     and     r6, lr, r12, lsr #15\r
1489     ldrh    r6, [r3, r6]\r
1490     and     r12,lr, r12, lsr #23\r
1491     ldrh    r12,[r3, r12]              @ 1c.i.\r
1492     orr     r4, r4, r5, lsl #16\r
1493     orr     r5, r6, r12,lsl #16\r
1494 \r
1495     stmia   r0!, {r4,r5}\r
1496     bne     .fl_loopBGR444\r
1497 \r
1498 \r
1499     ldmfd   sp!, {r4-r6,lr}\r
1500     bx lr\r
1501 \r
1502 \r
1503 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
1504 \r
1505 \r
1506 @ hilights 2 pixels in RGB555/BGR555 format\r
1507 .macro TileDoShHi2Pixels555 reg\r
1508     adds    \reg, \reg, #0x40000000\r
1509     orrcs   \reg, \reg, #0xf0000000\r
1510     mov     \reg, \reg, ror #27\r
1511     adds    \reg, \reg, #0x40000000\r
1512     orrcs   \reg, \reg, #0xf0000000\r
1513     mov     \reg, \reg, ror #26\r
1514     adds    \reg, \reg, #0x40000000\r
1515     orrcs   \reg, \reg, #0xf0000000\r
1516     mov     \reg, \reg, ror #27\r
1517     adds    \reg, \reg, #0x40000000\r
1518     orrcs   \reg, \reg, #0xf0000000\r
1519     mov     \reg, \reg, ror #27\r
1520     adds    \reg, \reg, #0x40000000\r
1521     orrcs   \reg, \reg, #0xf0000000\r
1522     mov     \reg, \reg, ror #26\r
1523     adds    \reg, \reg, #0x40000000\r
1524     orrcs   \reg, \reg, #0xf0000000\r
1525     mov     \reg, \reg, ror #27\r
1526 .endm\r
1527 \r
1528 \r
1529 @ Convert 0000bbb0 ggg0rrr0\r
1530 @ to      rrrrrggg gggbbbbb\r
1531 \r
1532 @ r2,r3,r9 - scratch, lr = 0x001c001c, r8 = 0x00030003\r
1533 .macro convRGB565 reg\r
1534     and     r2,   lr,   \reg,lsl #1\r
1535     and     r9,   r8,   \reg,lsr #2\r
1536     orr     r2,   r2,   r9           @ r2=red\r
1537     and     r3,   lr,   \reg,lsr #7\r
1538     and     r9,   r8,   \reg,lsr #10\r
1539     orr     r3,   r3,   r9           @ r3=blue\r
1540     and     \reg, \reg, lr,  lsl #3\r
1541     orr     \reg, \reg, \reg,lsl #3  @ green\r
1542     orr     \reg, \reg, r2,  lsl #11 @ add red back\r
1543     orr     \reg, \reg, r3           @ add blue back\r
1544 .endm\r
1545 \r
1546 .global vidConvCpyRGB565\r
1547 \r
1548 vidConvCpyRGB565: @ void *to, void *from, int pixels\r
1549     stmfd   sp!, {r4-r9,lr}\r
1550 \r
1551     mov     r12, r2, lsr #3  @ repeats\r
1552     mov     lr, #0x001c0000\r
1553     orr     lr, lr,  #0x01c  @ lr == pattern 0x001c001c\r
1554     mov     r8, #0x00030000\r
1555     orr     r8, r8,  #0x003\r
1556 \r
1557 .loopRGB565:\r
1558     ldmia   r1!, {r4-r7}\r
1559     subs    r12, r12, #1\r
1560     convRGB565 r4\r
1561     str     r4, [r0], #4\r
1562     convRGB565 r5\r
1563     str     r5, [r0], #4\r
1564     convRGB565 r6\r
1565     str     r6, [r0], #4\r
1566     convRGB565 r7\r
1567     str     r7, [r0], #4\r
1568 \r
1569     bgt     .loopRGB565\r
1570 \r
1571     ldmfd   sp!, {r4-r9,lr}\r
1572     bx      lr\r
1573 \r
1574 \r
1575 \r
1576 .global FinalizeLineRGB555 @ int sh\r
1577 \r
1578 FinalizeLineRGB555:\r
1579     stmfd   sp!, {r4-r8,lr}\r
1580     ldr     r8, =(Pico+0x22228)  @ Pico.video\r
1581     ldr     r4, =HighPal\r
1582 \r
1583     ldrb    r7, [r8, #-0x1a]     @ 0x2220e ~ dirtyPal\r
1584     mov     r6, r0\r
1585     mov     r1, #0\r
1586     tst     r7, r7\r
1587     beq     .fl_noconvRGB555\r
1588     strb    r1, [r8, #-0x1a]\r
1589     sub     r1, r8, #0x128       @ r1=Pico.cram\r
1590     mov     r0, r4\r
1591     mov     r2, #0x40\r
1592     bl      vidConvCpyRGB565\r
1593 \r
1594 .fl_noconvRGB555:\r
1595     mov     r3, r4\r
1596     tst     r6, r6\r
1597     beq     .fl_noshRGB555\r
1598     tst     r7, r7\r
1599     beq     .fl_noshRGB555\r
1600 \r
1601     @ shadowed pixels:\r
1602     mov     r12,    #0x008e\r
1603     orr     r12,r12,#0x7300\r
1604     orr     r12,r12,r12,lsl #16\r
1605     add     r4, r3, #0x40*2\r
1606     add     r5, r3, #0xc0*2\r
1607     mov     lr, #0x40/4\r
1608 .fl_loopcpRGB555_sh:\r
1609     ldmia   r3!, {r1,r6}\r
1610     subs    lr, lr, #1\r
1611     and     r1, r12, r1, lsr #1\r
1612     and     r6, r12, r6, lsr #1\r
1613     stmia   r4!, {r1,r6}\r
1614     stmia   r5!, {r1,r6}\r
1615     bne     .fl_loopcpRGB555_sh\r
1616 \r
1617     @ hilighted pixels:\r
1618     sub     r3, r3, #0x40*2\r
1619     mov     lr, #0x40/2\r
1620 .fl_loopcpRGB555_hi:\r
1621     ldr     r1, [r3], #4\r
1622     TileDoShHi2Pixels555 r1\r
1623     str     r1, [r4], #4\r
1624     subs    lr, lr, #1\r
1625     bne     .fl_loopcpRGB555_hi\r
1626 \r
1627     sub     r3, r3, #0x40*2\r
1628     mov     r6, #1\r
1629 \r
1630 .fl_noshRGB555:\r
1631     ldr     r12,=rendstatus\r
1632     eors    r6, r6, #1          @ sh is 0\r
1633     ldr     r12,[r12]\r
1634     mov     lr, #0xff\r
1635     tstne   r12,#(1<<2)         @ and PDRAW_ACC_SPRITES\r
1636     movne   lr, #0x3f\r
1637 \r
1638 .if OVERRIDE_HIGHCOL\r
1639     ldr     r1, =HighCol\r
1640     ldr     r0, =DrawLineDest\r
1641     ldr     r1, [r1]\r
1642     ldr     r0, [r0]\r
1643     add     r1, r1, #8\r
1644 .else\r
1645     ldr     r0, =DrawLineDest\r
1646     ldr     r1, =(HighCol+8)\r
1647     ldr     r0, [r0]\r
1648 .endif\r
1649 \r
1650     ldrb    r12, [r8, #12]\r
1651     mov     lr, lr, lsl #1\r
1652 \r
1653     tst     r12, #1\r
1654     movne   r2, #320/8           @ len\r
1655     bne     .fl_no32colRGB555\r
1656     ldr     r4, =PicoOpt\r
1657     mov     r2, #256/8\r
1658     ldr     r4, [r4]\r
1659     tst     r4, #0x4000\r
1660     bne     .fl_32scale_RGB555\r
1661     tst     r4, #0x0100\r
1662     addeq   r0, r0, #32*2\r
1663 \r
1664 .fl_no32colRGB555:\r
1665 \r
1666 .if UNALIGNED_DRAWLINEDEST\r
1667     @ this is basically for Gizmondo, which has unaligned odd lines in the framebuffer\r
1668     tst     r0, #2\r
1669     bne     .fl_RGB555u\r
1670 .endif\r
1671 \r
1672 .fl_loopRGB555:\r
1673     ldr     r12, [r1], #4\r
1674     ldr     r7,  [r1], #4\r
1675 \r
1676     and     r4, lr, r12, lsl #1\r
1677     ldrh    r4, [r3, r4]\r
1678     and     r5, lr, r12, lsr #7\r
1679     ldrh    r5, [r3, r5]\r
1680     and     r6, lr, r12, lsr #15\r
1681     ldrh    r6, [r3, r6]\r
1682     orr     r4, r4, r5, lsl #16\r
1683 \r
1684     and     r5, lr, r12, lsr #23\r
1685     ldrh    r5, [r3, r5]\r
1686     and     r8, lr, r7, lsl #1\r
1687     ldrh    r8, [r3, r8]\r
1688     orr     r5, r6, r5, lsl #16\r
1689 \r
1690     and     r6, lr, r7, lsr #7\r
1691     ldrh    r6, [r3, r6]\r
1692     and     r12,lr, r7, lsr #15\r
1693     ldrh    r12,[r3, r12]\r
1694     and     r7, lr, r7, lsr #23\r
1695     ldrh    r7, [r3, r7]\r
1696     orr     r8, r8, r6, lsl #16\r
1697 \r
1698     subs    r2, r2, #1\r
1699     orr     r12,r12, r7, lsl #16\r
1700 \r
1701     stmia   r0!, {r4,r5,r8,r12}\r
1702     bne     .fl_loopRGB555\r
1703 \r
1704     ldmfd   sp!, {r4-r8,lr}\r
1705     bx      lr\r
1706 \r
1707 \r
1708 .fl_32scale_RGB555:\r
1709     stmfd   sp!, {r9,r10}\r
1710     mov     r9, #0x3900 @ f800 07e0 001f | e000 0780 001c | 3800 01e0 0007\r
1711     orr     r9, r9, #0x00e7\r
1712 \r
1713 .if UNALIGNED_DRAWLINEDEST\r
1714     tst     r0, #2\r
1715     bne     .fl_32scale_RGB555u\r
1716 .endif\r
1717 \r
1718 .fl_loop32scale_RGB555:\r
1719     ldr     r12, [r1], #4\r
1720     ldr     r7,  [r1], #4\r
1721 \r
1722     and     r4, lr, r12,lsl #1\r
1723     ldrh    r4, [r3, r4]\r
1724     and     r5, lr, r12,lsr #7\r
1725     ldrh    r5, [r3, r5]\r
1726     and     r4, r4, r9, lsl #2\r
1727     orr     r4, r4, r4, lsl #14       @ r4[31:16] = 1/4 pix_s 0\r
1728     and     r5, r5, r9, lsl #2\r
1729     sub     r6, r5, r5, lsr #2        @ r6 = 3/4 pix_s 1\r
1730     add     r4, r4, r6, lsl #16       @ pix_d 0, 1\r
1731     and     r6, lr, r12,lsr #15\r
1732     ldrh    r6, [r3, r6]\r
1733     and     r12,lr, r12,lsr #23\r
1734     ldrh    r12,[r3, r12]\r
1735     and     r6, r6, r9, lsl #2\r
1736     add     r5, r5, r6\r
1737     mov     r5, r5, lsr #1\r
1738     sub     r6, r6, r6, lsr #2        @ r6 = 3/4 pix_s 2\r
1739     orr     r5, r5, r6, lsl #16\r
1740 \r
1741     and     r6, lr, r7, lsl #1\r
1742     ldrh    r6, [r3, r6]\r
1743     and     r12,r12,r9, lsl #2\r
1744     add     r5, r5, r12,lsl #14       @ pix_d 2, 3\r
1745     and     r6, r6, r9, lsl #2\r
1746     orr     r6, r12,r6, lsl #16       @ pix_d 4, 5\r
1747 \r
1748     and     r12,lr, r7, lsr #7\r
1749     ldrh    r12,[r3, r12]\r
1750     and     r10,lr, r7, lsr #15\r
1751     ldrh    r10,[r3, r10]\r
1752     and     r12,r12,r9, lsl #2\r
1753     sub     r8, r12,r12,lsr #2        @ r8 = 3/4 pix_s 1\r
1754     add     r8, r8, r6, lsr #18\r
1755     and     r7, lr, r7, lsr #23\r
1756     ldrh    r7, [r3, r7]\r
1757     and     r10,r10,r9, lsl #2\r
1758     orr     r8, r8, r10,lsl #15\r
1759     add     r8, r8, r12,lsl #15       @ pix_d 6, 7\r
1760     sub     r10,r10,r10,lsr #2        @ r10= 3/4 pix_s 2\r
1761     and     r7, r7, r9, lsl #2\r
1762     add     r10,r10,r7, lsr #2        @ += 1/4 pix_s 3\r
1763     orr     r10,r10,r7, lsl #16       @ pix_d 8, 9\r
1764 \r
1765     subs    r2, r2, #1\r
1766 \r
1767     stmia   r0!, {r4,r5,r6,r8,r10}\r
1768     bne     .fl_loop32scale_RGB555\r
1769 \r
1770     ldmfd   sp!, {r9,r10}\r
1771     ldmfd   sp!, {r4-r8,lr}\r
1772     bx      lr\r
1773 \r
1774 .if UNALIGNED_DRAWLINEDEST\r
1775     @ unaligned versions of loops\r
1776     @ warning: starts drawing 2bytes before dst\r
1777 \r
1778 .fl_RGB555u:\r
1779     sub     r0, r0, #2              @ initial adjustment\r
1780     mov     r8, #0\r
1781 \r
1782 .fl_loopRGB555u:\r
1783     ldr     r12, [r1], #4\r
1784     ldr     r7,  [r1], #4\r
1785 \r
1786     and     r6, lr, r12,lsl #1\r
1787     ldrh    r6, [r3, r6]\r
1788     and     r5, lr, r12,lsr #7\r
1789     ldrh    r5, [r3, r5]\r
1790     orr     r4, r8, r6, lsl #16\r
1791 \r
1792     and     r6, lr, r12,lsr #15\r
1793     ldrh    r6, [r3, r6]\r
1794     and     r8, lr, r12,lsr #23\r
1795     ldrh    r8, [r3, r8]\r
1796     orr     r5, r5, r6, lsl #16\r
1797 \r
1798     and     r6, lr, r7, lsl #1\r
1799     ldrh    r6, [r3, r6]\r
1800     and     r12,lr, r7, lsr #7\r
1801     ldrh    r12,[r3, r12]\r
1802     orr     r6, r8, r6, lsl #16\r
1803 \r
1804     and     r8, lr, r7, lsr #15\r
1805     ldrh    r8, [r3, r8]\r
1806     and     r7, lr, r7, lsr #23\r
1807 \r
1808     subs    r2, r2, #1\r
1809     orr     r12,r12,r8, lsl #16\r
1810     ldrh    r8, [r3, r7]\r
1811 \r
1812     stmia   r0!, {r4,r5,r6,r12}\r
1813     bne     .fl_loopRGB555u\r
1814 \r
1815     strh    r8, [r0], #2\r
1816 \r
1817     ldmfd   sp!, {r4-r8,lr}\r
1818     bx      lr\r
1819 \r
1820 \r
1821 .fl_32scale_RGB555u:\r
1822     sub     r0, r0, #2              @ initial adjustment\r
1823     mov     r4, #0\r
1824 \r
1825     @ r9  f800 07e0 001f | e000 0780 001c | 3800 01e0 0007\r
1826 .fl_loop32scale_RGB555u:\r
1827     ldr     r12, [r1], #4\r
1828     ldr     r7,  [r1], #4\r
1829 \r
1830     and     r6, lr, r12,lsl #1\r
1831     ldrh    r6, [r3, r6]\r
1832     and     r5, lr, r12,lsr #7\r
1833     ldrh    r5, [r3, r5]\r
1834     and     r6, r6, r9, lsl #2\r
1835     orr     r4, r4, r6, lsl #16       @ r4 = pix_d -1, 0\r
1836 \r
1837     and     r5, r5, r9, lsl #2\r
1838     sub     r8, r5, r5, lsr #2        @ r8 = 3/4 pix_s 1\r
1839     add     r6, r8, r6, lsr #2        @ r6 = (1/4 pix_s 0) + (3/4 pix_s 1)\r
1840     orr     r5, r6, r5, lsl #15\r
1841 \r
1842     and     r6, lr, r12,lsr #15\r
1843     ldrh    r6, [r3, r6]\r
1844     and     r12,lr, r12,lsr #23\r
1845     ldrh    r12,[r3, r12]\r
1846     and     r6, r6, r9, lsl #2\r
1847     add     r5, r5, r6, lsl #15       @ r5 = pix_d 1, 2\r
1848 \r
1849     and     r8, lr, r7, lsl #1\r
1850     ldrh    r8, [r3, r8]\r
1851     and     r10,lr, r7, lsr #7\r
1852     ldrh    r10,[r3, r10]\r
1853     and     r12,r12,r9, lsl #2\r
1854     sub     r6, r6, r6, lsr #2        @ r6 = 3/4 pix_s 2\r
1855     add     r6, r6, r12,lsr #2\r
1856     orr     r6, r6, r12,lsl #16       @ r6 = pix_d 3, 4\r
1857 \r
1858     and     r8, r8, r9, lsl #2\r
1859     and     r10,r10,r9, lsl #2\r
1860     sub     r12,r10,r10,lsr #2        @ r12 = 3/4 pix_s 5\r
1861     orr     r8, r8, r8, lsl #14\r
1862     add     r8, r8, r12,lsl #16       @ r8 = pix_d 5, 6\r
1863     and     r12,lr, r7, lsr #15\r
1864     ldrh    r12,[r3, r12]\r
1865     and     r7, lr, r7, lsr #23\r
1866     ldrh    r7, [r3, r7]\r
1867     and     r12,r12,r9, lsl #2\r
1868     add     r10,r10,r12\r
1869     mov     r10,r10,    lsr #1\r
1870     sub     r12,r12,r12,lsr #2        @ r12 = 3/4 pix_s 6\r
1871     orr     r10,r10,r12,lsl #16\r
1872     and     r7, r7, r9, lsl #2\r
1873     add     r10,r10,r7, lsl #14       @ r10 = pix_d 7, 8\r
1874 \r
1875     subs    r2, r2, #1\r
1876 \r
1877     stmia   r0!, {r4,r5,r6,r8,r10}\r
1878     mov     r4, r7\r
1879     bne     .fl_loop32scale_RGB555u\r
1880 \r
1881     strh    r4, [r0], #2\r
1882 \r
1883     ldmfd   sp!, {r9,r10}\r
1884     ldmfd   sp!, {r4-r8,lr}\r
1885     bx      lr\r
1886 \r
1887 .endif @ UNALIGNED_DRAWLINEDEST\r
1888 \r
1889 \r
1890 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
1891 \r
1892 @ utility\r
1893 .global blockcpy @ void *dst, void *src, size_t n\r
1894 \r
1895 blockcpy:\r
1896     stmfd   sp!, {r4,r5}\r
1897     mov     r2, r2, lsr #4\r
1898 blockcpy_loop:\r
1899     ldmia   r1!, {r3-r5,r12}\r
1900     subs    r2, r2, #1\r
1901     stmia   r0!, {r3-r5,r12}\r
1902     bne     blockcpy_loop\r
1903     ldmfd   sp!, {r4,r5}\r
1904     bx      lr\r
1905 \r
1906 \r
1907 .global blockcpy_or @ void *dst, void *src, size_t n, int pat\r
1908 \r
1909 blockcpy_or:\r
1910     stmfd   sp!, {r4-r6}\r
1911     orr     r3, r3, r3, lsl #8\r
1912     orr     r3, r3, r3, lsl #16\r
1913     mov     r2, r2, lsr #4\r
1914 blockcpy_loop_or:\r
1915     ldmia   r1!, {r4-r6,r12}\r
1916     subs    r2, r2, #1\r
1917     orr     r4, r4, r3\r
1918     orr     r5, r5, r3\r
1919     orr     r6, r6, r3\r
1920     orr     r12,r12,r3\r
1921     stmia   r0!, {r4-r6,r12}\r
1922     bne     blockcpy_loop_or\r
1923     ldmfd   sp!, {r4-r6}\r
1924     bx      lr\r
1925 \r