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