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