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