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