initial import
[picodrive.git] / Pico / Draw.s
1 @ assembly "optimized" version of some funtions from draw.c\r
2 @ this is highly specialized, be careful if changing related C code!\r
3 \r
4 @ (c) Copyright 2006, notaz\r
5 @ All Rights Reserved\r
6 \r
7 \r
8 .extern Pico\r
9 .extern PicoOpt\r
10 .extern HighCol\r
11 .extern Scanline\r
12 .extern HighSprZ\r
13 .extern rendstatus\r
14 .extern DrawLineDest\r
15 .extern DrawStripVSRam\r
16 .extern DrawStripInterlace\r
17 \r
18 \r
19 @ helper\r
20 .macro TilePixel pat lsrr offs\r
21 .if !\lsrr\r
22     ands    r4, \pat, r2\r
23 .else\r
24     ands    r4, \pat, r2, lsr #\lsrr\r
25 .endif\r
26     orrne   r4, r3, r4\r
27     strneb  r4, [r1,#\offs]\r
28 .endm\r
29 \r
30 @ TileNorm (r1=pdest, r2=pixels8, r3=pal) r4: scratch, pat: register with helper pattern 0xf\r
31 .macro TileNorm pat\r
32     TilePixel \pat, 12, 0         @ #0x0000f000\r
33     TilePixel \pat,  8, 1         @ #0x00000f00\r
34     TilePixel \pat,  4, 2         @ #0x000000f0\r
35     TilePixel \pat,  0, 3         @ #0x0000000f\r
36     TilePixel \pat, 28, 4         @ #0xf0000000\r
37     TilePixel \pat, 24, 5         @ #0x0f000000\r
38     TilePixel \pat, 20, 6         @ #0x00f00000\r
39     TilePixel \pat, 16, 7         @ #0x000f0000\r
40 .endm\r
41 \r
42 @ TileFlip (r1=pdest, r2=pixels8, r3=pal) r4: scratch, pat: register with helper pattern 0xf\r
43 .macro TileFlip pat\r
44     TilePixel \pat, 16, 0         @ #0x000f0000\r
45     TilePixel \pat, 20, 1         @ #0x00f00000\r
46     TilePixel \pat, 24, 2         @ #0x0f000000\r
47     TilePixel \pat, 28, 3         @ #0xf0000000\r
48     TilePixel \pat,  0, 4         @ #0x0000000f\r
49     TilePixel \pat,  4, 5         @ #0x000000f0\r
50     TilePixel \pat,  8, 6         @ #0x00000f00\r
51     TilePixel \pat, 12, 7         @ #0x0000f000\r
52 .endm\r
53 \r
54 @ shadow/hilight mode\r
55 \r
56 @ this one is for hi priority layer\r
57 .macro TilePixelShHP lsrr offs\r
58 .if !\lsrr\r
59     ands    r4, r12, r2\r
60 .else\r
61     ands    r4, r12, r2, lsr #\lsrr\r
62 .endif\r
63     ldreqb  r4, [r1,#\offs]\r
64     orrne   r4, r3, r4\r
65     strneb  r4, [r1,#\offs]\r
66     tsteq   r4, #0x80\r
67     andeq   r4, r4, #0x3f\r
68     streqb  r4, [r1,#\offs]\r
69 .endm\r
70 \r
71 @ TileNorm (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: register with helper pattern 0xf, touches r3 high bits\r
72 .macro TileNormShHP\r
73     TilePixelShHP 12, 0         @ #0x0000f000\r
74     TilePixelShHP  8, 1         @ #0x00000f00\r
75     TilePixelShHP  4, 2         @ #0x000000f0\r
76     TilePixelShHP  0, 3         @ #0x0000000f\r
77     TilePixelShHP 28, 4         @ #0xf0000000\r
78     TilePixelShHP 24, 5         @ #0x0f000000\r
79     TilePixelShHP 20, 6         @ #0x00f00000\r
80     TilePixelShHP 16, 7         @ #0x000f0000\r
81 .endm\r
82 \r
83 @ TileFlip (r1=pdest, r2=pixels8, r3=pal) r4: scratch, pat: register with helper pattern 0xf\r
84 .macro TileFlipShHP\r
85     TilePixelShHP 16, 0         @ #0x000f0000\r
86     TilePixelShHP 20, 1         @ #0x00f00000\r
87     TilePixelShHP 24, 2         @ #0x0f000000\r
88     TilePixelShHP 28, 3         @ #0xf0000000\r
89     TilePixelShHP  0, 4         @ #0x0000000f\r
90     TilePixelShHP  4, 5         @ #0x000000f0\r
91     TilePixelShHP  8, 6         @ #0x00000f00\r
92     TilePixelShHP 12, 7         @ #0x0000f000\r
93 .endm\r
94 \r
95 \r
96 @ TileSingleSh (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=sx; r12: helper pattern 0xf\r
97 .macro TileSingleSh\r
98     tst     r0, #1              @ not aligned?\r
99     mov     r7, #0x00c000\r
100     orr     r7, r7, #0xc0\r
101     ldrneb  r4, [r1]\r
102     ldreqh  r4, [r1]\r
103     orr     r4, r4, r7\r
104     strneb  r4, [r1], #1\r
105     streqh  r4, [r1], #2\r
106     ldrh    r4, [r1]\r
107     orr     r4, r4, r7\r
108     strh    r4, [r1], #2\r
109     ldrh    r4, [r1]\r
110     orr     r4, r4, r7\r
111     strh    r4, [r1], #2\r
112     ldrh    r4, [r1]\r
113     orr     r4, r4, r7\r
114     strh    r4, [r1], #2\r
115     ldrneb  r4, [r1]\r
116     orr     r4, r4, r7\r
117     strneb  r4, [r1], #1\r
118 .endm\r
119 \r
120 @ TileSingleHi (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=sx, r12: register with helper pattern 0xf\r
121 .macro TileSingleHi\r
122     tst     r1,  #1              @ not aligned?\r
123     mov     r7,  #0x008000\r
124     orr     r7,  r7, #0x80\r
125     ldrneb  r4,  [r1], #1\r
126     ldreqh  r4,  [r1], #2        @ 1ci\r
127     ldrh    r12, [r1], #2\r
128     bic     r4,  r4,  r7, lsr #1\r
129     orr     r4,  r4,  r7\r
130     strneb  r4,  [r1, #-3]\r
131     streqh  r4,  [r1, #-4]\r
132     ldrh    r4,  [r1], #2\r
133     bic     r12, r12, r7, lsr #1\r
134     orr     r12, r12, r7\r
135     strh    r12, [r1, #-4]\r
136     ldrh    r12, [r1], #2\r
137     bic     r4,  r4,  r7, lsr #1\r
138     orr     r4,  r4,  r7\r
139     strh    r4,  [r1, #-4]\r
140     ldrneb  r4,  [r1]\r
141     bic     r12, r12, r7, lsr #1\r
142     orr     r12, r12, r7\r
143     strh    r12, [r1, #-2]\r
144     bicne   r4,  r4,  r7, lsr #1\r
145     orrne   r4,  r4,  r7\r
146     strneb  r4,  [r1], #1\r
147     mov     r12, #0xf\r
148 .endm\r
149 \r
150 .macro TileDoShGenPixel shift ofs\r
151 .if \shift\r
152     ands    r4, r12, r2, lsr #\shift\r
153 .else\r
154     ands    r4, r12, r2\r
155 .endif\r
156     beq     3f\r
157     cmp     r4, #0xe\r
158     beq     2f\r
159     bgt     1f\r
160     orr     r4, r3, r4\r
161     strb    r4, [r1,#\ofs]\r
162     b       3f\r
163 1:\r
164     ldrb    r4, [r1,#\ofs]        @ 2ci\r
165     orr     r4, r4, #0xc0\r
166     strb    r4, [r1,#\ofs]\r
167     b       3f\r
168 2:\r
169     ldrb    r4, [r1,#\ofs]        @ 2ci\r
170     bic     r4, r4, #0xc0\r
171     orr     r4, r4, #0x80\r
172     strb    r4, [r1,#\ofs]\r
173 3:\r
174 .endm\r
175 \r
176 @ TileFlipSh (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=sx, r12: register with helper pattern 0xf\r
177 .macro TileFlipSh\r
178     TileDoShGenPixel 16,  0 @ #0x000f0000\r
179     TileDoShGenPixel 20,  1 @ #0x00f00000\r
180     TileDoShGenPixel 24,  2 @ #0x0f000000\r
181     TileDoShGenPixel 28,  3 @ #0xf0000000\r
182     TileDoShGenPixel  0,  4 @ #0x0000000f\r
183     TileDoShGenPixel  4,  5 @ #0x000000f0\r
184     TileDoShGenPixel  8,  6 @ #0x00000f00\r
185     TileDoShGenPixel 12,  7 @ #0x0000f000\r
186 .endm\r
187 \r
188 @ TileNormSh (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=sx, r12: register with helper pattern 0xf\r
189 .macro TileNormSh\r
190     TileDoShGenPixel 12,  0 @ #0x0000f000\r
191     TileDoShGenPixel  8,  1 @ #0x00000f00\r
192     TileDoShGenPixel  4,  2 @ #0x000000f0\r
193     TileDoShGenPixel  0,  3 @ #0x0000000f\r
194     TileDoShGenPixel 28,  4 @ #0xf0000000\r
195     TileDoShGenPixel 24,  5 @ #0x0f000000\r
196     TileDoShGenPixel 20,  6 @ #0x00f00000\r
197     TileDoShGenPixel 16,  7 @ #0x000f0000\r
198 .endm\r
199 \r
200 \r
201 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
202 \r
203 @ struct TileStrip\r
204 @ {\r
205 @   int nametab; // 0x00\r
206 @   int line;    // 0x04\r
207 @   int hscroll; // 0x08\r
208 @   int xmask;   // 0x0C\r
209 @   int *hc;     // 0x10 (pointer to cache buffer)\r
210 @   int cells;   // 0x14\r
211 @ };\r
212 \r
213 @ int DrawLayer(int plane, int *hcache, int maxcells, int sh)\r
214 \r
215 .global DrawLayer @ int plane, int *hcache, int maxcells, int sh\r
216 \r
217 DrawLayer:\r
218     stmfd   sp!, {r4-r11,lr}\r
219 \r
220     ldr     r11, =(Pico+0x22228)  @ Pico.video\r
221     mov     r8, #1\r
222 \r
223     ldrb    r7, [r11, #16]        @ ??hh??ww\r
224 \r
225     mov     r6, r1                @ hcache\r
226     orr     r9, r2, r3, lsl #31   @ r9=maxcells|(sh<<31)\r
227 \r
228     mov     r1, r7, lsl #4\r
229     orr     r1, r1, #0x00ff\r
230 \r
231     and     r10, r7,  #3\r
232     cmp     r10, #1\r
233     biclt   r1,  r1, #0xfc00\r
234     biceq   r1,  r1, #0xfe00\r
235     bicgt   r1,  r1, #0xff00      @ r1=ymask=(height<<8)|0xff; ...; // Y Mask in pixels\r
236 \r
237     add     r10, r10, #5\r
238     cmp     r10, #7\r
239     subge   r10, r10, #1          @ r10=shift[width] (5,6,6,7)\r
240 \r
241     @ calculate xmask:\r
242     mov     r5, r8, lsl r10\r
243     sub     r5, r5, #1            @ r5=xmask\r
244 \r
245     @ Find name table:\r
246     tst     r0,  r0\r
247     ldreqb  r12, [r11, #2]\r
248     ldrneb  r12, [r11, #4]\r
249 \r
250     ldr     r2, =Scanline         @ trying to make good use of pipeline here\r
251     ldr     lr, =(Pico+0x10000)   @ lr=Pico.vram\r
252 \r
253     moveq   r12, r12, lsl #10\r
254     movne   r12, r12, lsl #13\r
255     and     r12, r12, #(7<<13)    @ r12=(ts->nametab<<1) (halfword compliant)\r
256 \r
257     ldrh    r8, [r11, #12]\r
258     ldrb    r7, [r11, #11]\r
259     ldr     r2, [r2]\r
260 \r
261     mov     r4, r8, lsr #8        @ pvid->reg[13]\r
262     mov     r4, r4, lsl #10       @ htab=pvid->reg[13]<<9; (halfwords)\r
263     tst     r7, #2\r
264     addne   r4, r4, r2, lsl #2    @ htab+=Scanline<<1; // Offset by line\r
265     tst     r7, #1\r
266     biceq   r4, r4, #0x1f         @ htab&=~0xf; // Offset by tile\r
267     add     r4, r4, r0, lsl #1    @ htab+=plane\r
268     bic     r4, r4, #0x00ff0000   @ just in case\r
269     ldrh    r3, [lr, r4]          @ r3=hscroll\r
270 \r
271     tst     r7, #4\r
272     bne     .DrawStrip_vsscroll\r
273 \r
274     @ Get vertical scroll value:\r
275     add     r7, lr,  #0x012000\r
276     add     r7, r7,  #0x000180    @ r7=Pico.vsram (Pico+0x22180)\r
277     ldr     r7, [r7]\r
278 \r
279     tst     r8, #2\r
280     tstne   r8, #4\r
281     bne     .DrawStrip_interlace\r
282 \r
283     tst     r0, r0\r
284     movne   r7, r7, lsr #16\r
285 \r
286     @ Find the line in the name table\r
287     add     r2, r2, r7\r
288     and     r2, r2, r1\r
289     mov     r4, r2, lsr #3\r
290     add     r10, r10, #1           @ shift[width]++\r
291     add     r12, r12, r4, lsl r10  @ nametab+=(ts.line>>3)<<shift[width];\r
292 \r
293     @ ldmia   r0, {r1,r2,r3,r5,r6,r9} @ r2=line, r3=ts->hscroll, r5=ts->xmask, r6=ts->hc, r9=ts->cells\r
294 @    mov     r12,r1,  lsl #1 @ r12=(ts->nametab<<1) (halfword compliant)\r
295 \r
296     and     r10,r2,  #7\r
297     mov     r10,r10, lsl #1 @ r10=ty=(ts->line&7)<<1;\r
298     orr     r10,r10, r9, lsl #24\r
299 \r
300     rsb     r8, r3, #0\r
301     mov     r8, r8, lsr #3  @ r8=tilex=(-ts->hscroll)>>3\r
302 \r
303     sub     r1, r3, #1\r
304     and     r1, r1, #7\r
305     add     r7, r1, #1      @ r7=dx=((ts->hscroll-1)&7)+1\r
306 \r
307     tst     r9, #1<<31\r
308     mov     r3, #0\r
309     orrne   r10,r10, #1<<23 @ r10=(cells<<24|sh<<23|hi_not_empty<<22|ty)\r
310     movne   r3, #0x40       @ default to shadowed pal on sh mode\r
311 \r
312     mvn     r9, #0          @ r9=prevcode=-1\r
313 \r
314     cmp     r7, #8\r
315     addne   r10,r10, #0x01000000 @ we will loop cells+1 times if there is scroll\r
316 \r
317     @ cache some stuff to avoid mem access\r
318     ldr     r11,=HighCol\r
319     mov     r0, #0xf\r
320     add     r1, r11, r7         @ r1=pdest\r
321 \r
322 \r
323     @ r4 & r7 are scratch in this loop\r
324 .dsloop_subr1:\r
325     sub     r1, r1, #8\r
326 .dsloop: @ 40-41 times\r
327     subs    r10,r10, #0x01000000\r
328     bmi     .dsloop_exit\r
329 \r
330 .dsloop_enter:\r
331     and     r7, r5, r8\r
332     add     r7, lr, r7, lsl #1 @ Pico.vram+((tilex&ts->xmask) as halfwords)\r
333     ldrh    r7, [r7, r12]      @ r7=code (int, but from unsigned, no sign extend)\r
334 \r
335     add     r1, r1, #8\r
336     add     r8, r8, #1\r
337 \r
338     tst     r7, #0x8000\r
339     bne     .DrawStrip_hiprio\r
340 \r
341     cmp     r7, r9\r
342     beq     .DrawStrip_samecode @ we know stuff about this tile already\r
343 \r
344     mov     r9, r7          @ remember code\r
345 \r
346     movs    r2, r9, lsl #20 @ if (code&0x1000)\r
347     mov     r2, r2, lsl #1\r
348     add     r2, r2, r10, lsl #17\r
349     mov     r2, r2, lsr #17\r
350     eorcs   r2, r2, #0x0e   @ if (code&0x1000) addr^=0xe;\r
351 \r
352     ldr     r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
353 \r
354     bic     r7, r3, #0x3f\r
355     and     r3, r9, #0x6000\r
356     add     r3, r7, r3, lsr #9 @ r3=pal=((code&0x6000)>>9);\r
357 \r
358 .DrawStrip_samecode:\r
359     tst     r2, r2\r
360     beq     .dsloop              @ tileline blank\r
361 \r
362     cmp     r2, r2, ror #4\r
363     beq     .DrawStrip_SingleColor @ tileline singlecolor \r
364 \r
365     tst     r9, #0x0800\r
366     beq     .DrawStrip_TileNorm\r
367 \r
368     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r0: helper pattern\r
369     TileFlip r0\r
370     b       .dsloop\r
371 \r
372 .DrawStrip_TileNorm:\r
373     TileNorm r0\r
374     b       .dsloop\r
375 \r
376 .DrawStrip_SingleColor:\r
377     and     r4, r2, #0xf\r
378     orr     r4, r3, r4\r
379     orr     r4, r4, r4, lsl #8\r
380     tst     r1, #1             @ not aligned?\r
381     strneb  r4, [r1], #1\r
382     streqh  r4, [r1], #2\r
383     strh    r4, [r1], #2\r
384     strh    r4, [r1], #2\r
385     strh    r4, [r1], #2\r
386     strneb  r4, [r1], #1       @ have a remaining unaligned pixel?\r
387     b       .dsloop_subr1\r
388 \r
389 .DrawStrip_hiprio:\r
390     tst     r10, #0x00c00000\r
391     beq     .DrawStrip_hiprio_maybempt\r
392     sub     r0, r1, r11\r
393     orr     r7, r7, r0,  lsl #16\r
394     orr     r7, r7, r10, lsl #25 @ (ty<<25)\r
395     tst     r7, #0x1000\r
396     eorne   r7, r7, #7<<26  @ if(code&0x1000) cval^=7<<26;\r
397     str     r7, [r6], #4    @ cache hi priority tile\r
398     mov     r0, #0xf\r
399     b       .dsloop\r
400 \r
401 .DrawStrip_hiprio_maybempt:\r
402     cmp     r7, r9\r
403     beq     .dsloop         @ must've been empty, otherwise we wouldn't get here\r
404     movs    r2, r7, lsl #20 @ if (code&0x1000)\r
405     mov     r2, r2, lsl #1\r
406     add     r2, r2, r10, lsl #17\r
407     mov     r2, r2, lsr #17\r
408     eorcs   r2, r2, #0x0e   @ if (code&0x1000) addr^=0xe;\r
409     ldr     r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
410     mov     r9, r7          @ remember code\r
411     tst     r2, r2\r
412     orrne   r10, r10, #1<<22\r
413     bne     .DrawStrip_hiprio\r
414     b       .dsloop\r
415 \r
416 .dsloop_exit:\r
417     mov     r0, #0\r
418     str     r0, [r6]    @ terminate the cache list\r
419 \r
420     ldmfd   sp!, {r4-r11,lr}\r
421     bx      lr\r
422 \r
423 \r
424 .DrawStrip_vsscroll:\r
425     @ shit, we have 2-cell column based vscroll\r
426     @ let the c code handle this (for now)\r
427 \r
428     @   int nametab; // 0x00\r
429     @   int line;    // 0x04\r
430     @   int hscroll; // 0x08\r
431     @   int xmask;   // 0x0C\r
432     @   int *hc;     // 0x10 (pointer to cache buffer)\r
433     @   int cells;   // 0x14\r
434 \r
435     sub     sp, sp, #6*4\r
436     orr     r2, r1, r10, lsl #24 @ ts.line=ymask|(shift[width]<<24); // save some stuff instead of line\r
437     mov     r1, r0               @ plane\r
438     mov     r0, r12, lsr #1      @ halfwords\r
439     and     r9, r9, #0xff\r
440     stmia   sp, {r0,r2,r3,r5,r6,r9}\r
441 \r
442     mov     r0, sp\r
443     bl      DrawStripVSRam @ struct TileStrip *ts, int plane\r
444 \r
445     add     sp, sp, #6*4\r
446     ldmfd   sp!, {r4-r11,lr}\r
447     bx      lr\r
448 \r
449 @ interlace mode 2? Sonic 2?\r
450 .DrawStrip_interlace:\r
451     tst     r0, r0\r
452     moveq   r7, r7, lsl #21\r
453     movne   r7, r7, lsl #5\r
454 \r
455     @ Find the line in the name table\r
456     add     r2, r7, r2, lsl #22    @ r2=(vscroll+(Scanline<<1))<<21 (11 bits);\r
457     orr     r1, r1, #0x80000000\r
458     and     r2, r2, r1, ror #10    @ &((ymask<<1)|1)<<21;\r
459     mov     r2, r2, lsr #21\r
460     mov     r4, r2, lsr #4\r
461     mov     r12, r12, lsr #1       @ halfwords\r
462     add     r0, r12, r4, lsl r10   @ nametab+=(ts.line>>4)<<shift[width];\r
463     and     r9, r9, #0xff\r
464 \r
465     sub     sp, sp, #6*4\r
466     stmia   sp, {r0,r2,r3,r5,r6,r9}\r
467 \r
468     mov     r0, sp\r
469     bl      DrawStripInterlace @ struct TileStrip *ts\r
470 \r
471     add     sp, sp, #6*4\r
472     ldmfd   sp!, {r4-r11,lr}\r
473     bx      lr\r
474 \r
475 .pool\r
476 \r
477 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
478 \r
479 \r
480 .global BackFill @ int reg7, int sh\r
481 \r
482 BackFill:\r
483     stmfd   sp!, {r4-r9,lr}\r
484 \r
485     ldr     lr, =(HighCol+8)\r
486 \r
487     mov     r0, r0, lsl #26\r
488     mov     r0, r0, lsr #26\r
489     orr     r0, r0, r1, lsl #6\r
490     orr     r0, r0, r0, lsl #8\r
491     orr     r0, r0, r0, lsl #16\r
492 \r
493     mov     r1, r0\r
494     mov     r2, r0\r
495     mov     r3, r0\r
496     mov     r4, r0\r
497     mov     r5, r0\r
498     mov     r6, r0\r
499     mov     r7, r0\r
500 \r
501     @ go go go!\r
502     stmia   lr!, {r0-r7} @ 10*8*4\r
503     stmia   lr!, {r0-r7}\r
504     stmia   lr!, {r0-r7}\r
505     stmia   lr!, {r0-r7}\r
506     stmia   lr!, {r0-r7}\r
507     stmia   lr!, {r0-r7}\r
508     stmia   lr!, {r0-r7}\r
509     stmia   lr!, {r0-r7}\r
510     stmia   lr!, {r0-r7}\r
511     stmia   lr!, {r0-r7}\r
512 \r
513     ldmfd   sp!, {r4-r9,r12}\r
514     bx      r12\r
515 \r
516 \r
517 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
518 \r
519 \r
520 .global DrawTilesFromCache @ int *hc, int sh\r
521 \r
522 DrawTilesFromCache:\r
523     stmfd   sp!, {r4-r8,r11,lr}\r
524 \r
525     mvn     r5, #0         @ r5=prevcode=-1\r
526     mov     r8, r1\r
527 \r
528     @ cache some stuff to avoid mem access\r
529     ldr     r11,=HighCol\r
530     ldr     lr, =(Pico+0x10000) @ lr=Pico.vram\r
531     mov     r12,#0xf\r
532 \r
533     @ scratch: r4, r7\r
534 .dtfc_loop:\r
535     ldr     r6, [r0], #4    @ read code\r
536     movs    r1, r6, lsr #16 @ r1=dx;\r
537     ldmeqfd sp!, {r4-r8,r11,pc} @ dx is never zero, this must be a terminator, return\r
538     bic     r1, r1, #0xfe00\r
539     add     r1, r11, r1     @ r1=pdest\r
540 \r
541     mov     r7, r6, lsl #16\r
542     cmp     r5, r7, lsr #16\r
543     beq     .dtfc_samecode  @ if (code==prevcode)\r
544 \r
545     mov     r5, r7, lsr #16\r
546 \r
547     mov     r2, r5, lsl #21\r
548     mov     r2, r2, lsr #17 @ r2=addr=(code&0x7ff)<<4;\r
549     add     r2, r2, r6, lsr #25 @ addr+=ty\r
550 \r
551     and     r3, r5, #0x6000\r
552     mov     r3, r3, lsr #9  @ r3=pal=((code&0x6000)>>9);\r
553 \r
554     ldr     r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
555 \r
556 .dtfc_samecode:\r
557     tst     r8, r8\r
558     bne     .dtfc_shadow\r
559 \r
560     tst     r2, r2\r
561     beq     .dtfc_loop\r
562 \r
563     cmp     r2, r2, ror #4\r
564     beq     .dtfc_SingleColor @ tileline singlecolor \r
565 \r
566     tst     r5, #0x0800\r
567     beq     .dtfc_TileNorm\r
568 \r
569     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
570     TileFlip r12\r
571     b       .dtfc_loop\r
572 \r
573 .dtfc_TileNorm:\r
574     TileNorm r12\r
575     b       .dtfc_loop\r
576 \r
577 .dtfc_SingleColor:\r
578     and     r4, r2, #0xf\r
579     orr     r4, r3, r4\r
580     orr     r4, r4, r4, lsl #8\r
581     tst     r1, #1              @ not aligned?\r
582     strneb  r4, [r1], #1\r
583     streqh  r4, [r1], #2\r
584     strh    r4, [r1], #2\r
585     strh    r4, [r1], #2\r
586     strh    r4, [r1], #2\r
587     strneb  r4, [r1], #1        @ have a remaining unaligned pixel?\r
588     b       .dtfc_loop\r
589 \r
590 .dtfc_shadow:\r
591     tst     r2, r2\r
592     beq     .dtfc_shadow_blank\r
593 \r
594     cmp     r2, r2, ror #4\r
595     beq     .dtfc_SingleColor @ tileline singlecolor \r
596 \r
597     tst     r5, #0x0800\r
598     beq     .dtfc_TileNormShHP\r
599 \r
600     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
601     TileFlipShHP\r
602     b       .dtfc_loop\r
603 \r
604 .dtfc_TileNormShHP:\r
605     TileNormShHP\r
606     b       .dtfc_loop\r
607 \r
608 .dtfc_shadow_blank:\r
609     ldrb    r4, [r1]        @ 1ci\r
610     ldrb    r12,[r1,#1]\r
611     tst     r4, #0x80\r
612     andeq   r4, r4,#0x3f\r
613     streqb  r4, [r1]\r
614     tst     r12,#0x80\r
615     ldrb    r4, [r1,#2]\r
616     andeq   r12,r12,#0x3f\r
617     streqb  r12,[r1,#1]\r
618     tst     r4, #0x80\r
619     ldrb    r12,[r1,#3]\r
620     andeq   r4, r4,#0x3f\r
621     streqb  r4, [r1,#2]\r
622     tst     r12,#0x80\r
623     ldrb    r4, [r1,#4]\r
624     andeq   r12,r12,#0x3f\r
625     streqb  r12,[r1,#3]\r
626     tst     r4, #0x80\r
627     ldrb    r12,[r1,#5]\r
628     andeq   r4, r4,#0x3f\r
629     streqb  r4, [r1,#4]\r
630     tst     r12,#0x80\r
631     ldrb    r4, [r1,#6]\r
632     andeq   r12,r12,#0x3f\r
633     streqb  r12,[r1,#5]\r
634     tst     r4, #0x80\r
635     ldrb    r12,[r1,#7]\r
636     andeq   r4, r4,#0x3f\r
637     streqb  r4, [r1,#6]\r
638     tst     r12,#0x80\r
639     andeq   r12,r12,#0x3f\r
640     streqb  r12,[r1,#7]\r
641     mov     r12, #0xf\r
642     b       .dtfc_loop\r
643 \r
644 .pool\r
645 \r
646 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
647 \r
648 \r
649 .global DrawSpritesFromCache @ int *hc, int sh\r
650 \r
651 DrawSpritesFromCache:\r
652     stmfd   sp!, {r4-r11,lr}\r
653 \r
654     @ cache some stuff to avoid mem access\r
655     ldr     r11,=HighCol\r
656     ldr     lr, =(Pico+0x10000) @ lr=Pico.vram\r
657     mov     r6, r1, lsl #31\r
658     orr     r6, r6, #1<<30\r
659     mov     r12,#0xf\r
660 \r
661     mov     r10, r0\r
662 \r
663 .dsfc_loop:\r
664     ldr     r9, [r10], #4    @ read code\r
665     bic     r6, r6, #7       @ using pipeline\r
666     tst     r9, r9\r
667     ldmeqfd sp!, {r4-r11,pc}\r
668 \r
669     mov     r4, r9, lsl #28\r
670     orr     r6, r6, r4, lsr #30\r
671     add     r6, r6, #1       @ r6=s1cc???? ... ?????www (s=shadow/hilight, cc=pal, w=width)\r
672 \r
673     and     r5, r9, #3\r
674     add     r5, r5, #1       @ r5=delta\r
675     tst     r9, #0x10000\r
676     rsbne   r5, r5, #0       @ Flip X\r
677     mov     r5, r5, lsl #4\r
678 \r
679     mov     r2, r9, lsr #17\r
680     mov     r8, r2, lsl #1   @ tile=((unsigned int)code>>17)<<1;\r
681 \r
682     and     r3, r9, #0x30    @ r3=pal=(code&0x30);\r
683 \r
684     bic     r6, r6, #3<<28\r
685     orr     r6, r6, r3, lsl #24\r
686 \r
687     mov     r0, r9, lsl #16\r
688     mov     r0, r0, asr #22  @ sx=(code<<16)>>22\r
689     adds    r0, r0, #0       @ set ZV\r
690     b       .dsfc_inloop_enter\r
691 \r
692 @ scratch: r4, r7\r
693 .dsfc_inloop:\r
694     sub     r6, r6, #1\r
695     tst     r6, #7\r
696     beq     .dsfc_loop\r
697     adds    r0, r0, #8\r
698     add     r8, r8, r5\r
699 \r
700 .dsfc_inloop_enter:\r
701     ble     .dsfc_inloop\r
702     cmp     r0, #328\r
703     bge     .dsfc_loop\r
704 \r
705     mov     r8, r8, lsl #17\r
706     mov     r8, r8, lsr #17   @ tile&=0x7fff; // Clip tile address\r
707 \r
708     ldr     r2, [lr, r8, lsl #1] @ pack=*(unsigned int *)(Pico.vram+tile); // Get 8 pixels\r
709     add     r1, r11, r0       @ r1=pdest\r
710     tst     r2, r2\r
711     beq     .dsfc_inloop\r
712 \r
713     cmp     r12, r6, lsr #28\r
714     beq     .dsfc_shadow\r
715 \r
716     cmp     r2, r2, ror #4\r
717     beq     .dsfc_SingleColor @ tileline singlecolor \r
718 \r
719     tst     r9, #0x10000\r
720     beq     .dsfc_TileNorm\r
721 \r
722     @ TileFlip (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
723     TileFlip r12\r
724     b       .dsfc_inloop\r
725 \r
726 .dsfc_TileNorm:\r
727     TileNorm r12\r
728     b       .dsfc_inloop\r
729 \r
730 .dsfc_SingleColor:\r
731     tst     r0, #1              @ not aligned?\r
732     and     r4, r2, #0xf\r
733     orr     r4, r3, r4\r
734     orr     r4, r4, r4, lsl #8\r
735     strneb  r4, [r1], #1\r
736     streqh  r4, [r1], #2\r
737     strh    r4, [r1], #2\r
738     strh    r4, [r1], #2\r
739     strh    r4, [r1], #2\r
740     strneb  r4, [r1], #1\r
741     b       .dsfc_inloop\r
742 \r
743 .dsfc_shadow:\r
744     cmp     r2, r2, ror #4\r
745     beq     .dsfc_singlec_sh\r
746 \r
747     tst     r9, #0x10000\r
748     beq     .dsfc_TileNorm_sh\r
749 \r
750     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
751     TileFlipSh\r
752     b       .dsfc_inloop\r
753 \r
754 .dsfc_TileNorm_sh:\r
755     TileNormSh\r
756     b       .dsfc_inloop\r
757 \r
758 .dsfc_singlec_sh:\r
759     cmp     r2, #0xe0000000\r
760     bcc     .dsfc_SingleColor   @ normal singlecolor tileline (carry inverted in ARM)\r
761     tst     r2, #0x10000000\r
762     bne     .dsfc_sh_sh\r
763     TileSingleHi\r
764     b       .dsfc_inloop\r
765 \r
766 .dsfc_sh_sh:\r
767     TileSingleSh\r
768     b       .dsfc_inloop\r
769 \r
770 .pool\r
771 \r
772 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
773 \r
774 @ + 0  :    hhhhvvvv ab--hhvv yyyyyyyy yyyyyyyy // a: offscreen h, b: offs. v, h: horiz. size\r
775 @ + 4  :    xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8\r
776 \r
777 .global DrawSprite @ unsigned int *sprite, int **hc, int sh\r
778 \r
779 DrawSprite:\r
780     stmfd   sp!, {r4-r9,r11,lr}\r
781 \r
782     ldr     r3, [r0]        @ sprite[0]\r
783     ldr     r7, =Scanline\r
784     mov     r6, r3, lsr #28\r
785     sub     r6, r6, #1      @ r6=width-1 (inc later)\r
786     mov     r5, r3, lsr #24\r
787     and     r5, r5, #7      @ r5=height\r
788 \r
789     mov     r4, r3, lsl #16 @ r4=sy<<16 (tmp)\r
790 \r
791     ldr     r7, [r7]\r
792     ldr     r9, [r0, #4]\r
793     sub     r7, r7, r4, asr #16 @ r7=row=Scanline-sy\r
794 \r
795     tst     r2, r2\r
796     mov     r2, r9, asr #16 @ r2=sx\r
797     bic     r9, r9, #0xfe000000\r
798     orrne   r9, r9, #1<<31  @ r9=code|(sh<<31)\r
799 \r
800     tst     r9, #0x1000\r
801     movne   r4, r5, lsl #3\r
802     subne   r4, r4, #1\r
803     subne   r7, r4, r7      @ if (code&0x1000) row=(height<<3)-1-row; // Flip Y\r
804 \r
805     mov     r8, r9, lsl #21\r
806     mov     r8, r8, lsr #21\r
807     add     r8, r8, r7, lsr #3 @ tile+=row>>3; // Tile number increases going down\r
808     \r
809     tst     r9, #0x0800\r
810     mlane   r8, r5, r6, r8  @ if (code&0x0800) { tile+=delta*(width-1);\r
811     rsbne   r5, r5, #0      @ delta=-delta; } // r5=delta now\r
812 \r
813     mov     r8, r8, lsl #4\r
814     and     r7, r7, #7\r
815     add     r8, r8, r7, lsl #1 @ tile+=(row&7)<<1; // Tile address\r
816 \r
817     tst     r9, #0x8000\r
818     bne     .dspr_cache       @ if(code&0x8000) // high priority - cache it\r
819 \r
820     @ cache some stuff to avoid mem access\r
821     ldr     r11,=HighCol\r
822     ldr     lr, =(Pico+0x10000) @ lr=Pico.vram\r
823     mov     r12,#0xf\r
824 \r
825     mov     r5, r5, lsl #4     @ delta<<=4; // Delta of address\r
826     and     r4, r9, #0x6000\r
827     orr     r9, r9, r4, lsl #16\r
828     orr     r9, r9, #0x10000000 @ r9=scc1 ???? ... <code> (s=shadow/hilight, cc=pal)\r
829 \r
830     tst     r9, #1<<31\r
831     mov     r3, r4, lsr #9     @ r3=pal=((code>>9)&0x30);\r
832     orrne   r3, r3, #0x40      @ shadow by default\r
833 \r
834     add     r6, r6, #1         @ inc now\r
835     adds    r0, r2, #0         @ mov sx to r0 and set ZV flags\r
836     b       .dspr_loop_enter\r
837 \r
838 .dspr_loop:\r
839     subs    r6, r6, #1         @ width--\r
840     ldmeqfd sp!, {r4-r9,r11,pc}@ return\r
841     adds    r0, r0, #8         @ sx+=8\r
842     add     r8, r8, r5         @ tile+=delta\r
843 \r
844 .dspr_loop_enter:\r
845     ble     .dspr_loop         @ sx <= 0\r
846     cmp     r0, #328\r
847     ldmgefd sp!, {r4-r9,r11,pc}@ return\r
848 \r
849     mov     r8, r8, lsl #17\r
850     mov     r8, r8, lsr #17    @ tile&=0x7fff; // Clip tile address\r
851 \r
852     ldr     r2, [lr, r8, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
853     add     r1, r11, r0        @ r1=pdest\r
854     tst     r2, r2\r
855     beq     .dspr_loop\r
856 \r
857     cmp     r12, r9, lsr #28\r
858     beq     .dspr_shadow\r
859 \r
860     cmp     r2, r2, ror #4\r
861     beq     .dspr_SingleColor @ tileline singlecolor \r
862 \r
863     tst     r9, #0x0800\r
864     beq     .dspr_TileNorm\r
865 \r
866     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
867     TileFlip r12\r
868     b       .dspr_loop\r
869 \r
870 @ scratch: r4, r7\r
871 .dspr_TileNorm:\r
872     TileNorm r12\r
873     b       .dspr_loop\r
874 \r
875 .dspr_SingleColor:\r
876     and     r4, r2, #0xf\r
877     orr     r4, r3, r4\r
878     orr     r4, r4, r4, lsl #8\r
879     tst     r0, #1              @ not aligned?\r
880     strneb  r4, [r1], #1\r
881     streqh  r4, [r1], #2\r
882     strh    r4, [r1], #2\r
883     strh    r4, [r1], #2\r
884     strh    r4, [r1], #2\r
885     strneb  r4, [r1], #1\r
886     b       .dspr_loop\r
887 \r
888 .dspr_shadow:\r
889     cmp     r2, r2, ror #4\r
890     beq     .dspr_singlec_sh\r
891 \r
892     tst     r9, #0x0800\r
893     beq     .dspr_TileNorm_sh\r
894 \r
895     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r12: helper pattern\r
896     TileFlipSh\r
897     b       .dspr_loop\r
898 \r
899 .dspr_TileNorm_sh:\r
900     TileNormSh\r
901     b       .dspr_loop\r
902 \r
903 .dspr_singlec_sh:\r
904     cmp     r2, #0xe0000000\r
905     bcc     .dspr_SingleColor   @ normal tileline\r
906     tst     r2, #0x10000000\r
907     bne     .dspr_sh_sh\r
908     TileSingleHi\r
909     b       .dspr_loop\r
910 \r
911 .dspr_sh_sh:\r
912     TileSingleSh\r
913     b       .dspr_loop\r
914 \r
915 \r
916 .dspr_cache:\r
917     @ *(*hc)++ = (tile<<16)|((code&0x0800)<<5)|((sx<<6)&0x0000ffc0)|((code>>9)&0x30)|((sprite[0]>>24)&0xf);\r
918     mov     r4, r8, lsl #16     @ tile\r
919     tst     r9, #0x0800\r
920     orrne   r4, r4, #0x10000    @ code&0x0800\r
921     mov     r2, r2, lsl #22\r
922     orr     r4, r4, r2, lsr #16 @ (sx<<6)&0x0000ffc0\r
923     and     r2, r9, #0x6000\r
924     orr     r4, r4, r2, lsr #9  @ (code>>9)&0x30\r
925     mov     r3, r3, lsl #12\r
926     ldr     r2, [r1]\r
927     orr     r4, r4, r3, lsr #28 @ (sprite[0]>>24)&0xf\r
928 \r
929     str     r4, [r2], #4\r
930     str     r2, [r1]\r
931 \r
932     ldmfd   sp!, {r4-r9,r11,lr}\r
933     bx      lr\r
934 \r
935 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
936 \r
937 .global DrawWindow @ int tstart, int tend, int prio, int sh // int *hcache\r
938 \r
939 DrawWindow:\r
940     stmfd   sp!, {r4-r11,lr}\r
941 \r
942     ldr     r11, =(Pico+0x22228)  @ Pico.video\r
943     ldr     r10, =Scanline\r
944     ldrb    r12, [r11, #3]        @ pvid->reg[3]\r
945 \r
946     ldr     r10, [r10]\r
947     ldr     r4,  [r11, #12]\r
948     mov     r5,  r10, lsr #3\r
949     and     r10, r10, #7\r
950     mov     r10, r10, lsl #1      @ r10=ty\r
951 \r
952     mov     r12, r12, lsl #10\r
953 \r
954     tst     r4, #1                @ 40 cell mode?\r
955     andne   r12, r12, #0xf000     @ 0x3c<<10\r
956     andeq   r12, r12, #0xf800\r
957     addne   r12, r12, r5, lsl #7\r
958     addeq   r12, r12, r5, lsl #6  @ nametab\r
959     add     r12, r12, r0, lsl #2  @ +starttile\r
960 \r
961     ldr     r6, =rendstatus\r
962     ldr     lr, =(Pico+0x10000) @ lr=Pico.vram\r
963     ldrb    r6, [r6]\r
964 \r
965     @ fetch the first code now\r
966     ldrh    r7, [lr, r12]\r
967 \r
968     ands    r6, r6, #2            @ we care about bit 1 only\r
969     orr     r6, r6, r2\r
970     bne     .dw_no_sameprio\r
971 \r
972     cmp     r2, r7, lsr #15\r
973     ldmnefd sp!, {r4-r11,pc}      @ assume that whole window uses same priority\r
974 \r
975 .dw_no_sameprio:\r
976     orr     r6, r6, r3, lsl #8    @ shadow mode\r
977 \r
978     sub     r8, r1, r0\r
979     mov     r8, r8, lsl #1        @ cells\r
980 \r
981     mvn     r9, #0                @ r9=prevcode=-1\r
982 \r
983     @ cache some stuff to avoid mem access\r
984     ldr     r11,=(HighCol+8)\r
985     add     r1, r11, r0, lsl #4 @ r1=pdest\r
986     mov     r0, #0xf\r
987     b       .dwloop_enter\r
988 \r
989     @ r4,r5 & r7 are scratch in this loop\r
990 .dwloop:\r
991     add     r1, r1, #8\r
992 .dwloop_nor1:\r
993     add     r12, r12, #2    @ halfwords\r
994     ldrh    r7, [lr, r12]   @ r7=code (int, but from unsigned, no sign extend)\r
995     subs    r8, r8, #1\r
996     beq     .dwloop_end     @ done\r
997 \r
998     eor     r5, r6, r7, lsr #15\r
999     tst     r5, #1\r
1000     orrne   r6, r6, #2      @ wrong pri\r
1001     bne     .dwloop\r
1002 \r
1003     cmp     r7, r9\r
1004     beq     .dw_samecode    @ we know stuff about this tile already\r
1005 \r
1006 .dwloop_enter:\r
1007     mov     r9, r7          @ remember code\r
1008 \r
1009     movs    r2, r9, lsl #20 @ if (code&0x1000)\r
1010     mov     r2, r2, lsl #1\r
1011     add     r2, r10, r2, lsr #17 @ r2=addr=(code&0x7ff)<<4; addr+=ty\r
1012     eorcs   r2, r2, #0x0e   @ if (code&0x1000) addr^=0xe;\r
1013 \r
1014     and     r3, r9, #0x6000\r
1015     mov     r3, r3, lsr #9  @ r3=pal=((code&0x6000)>>9);\r
1016 \r
1017     ldr     r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
1018 \r
1019 .dw_samecode:\r
1020     tst     r6, #0x100\r
1021     bne     .dw_shadow\r
1022 .dw_shadow_done:\r
1023     tst     r2, r2\r
1024     beq     .dwloop              @ tileline blank\r
1025 \r
1026     cmp     r2, r2, ror #4\r
1027     beq     .dw_SingleColor @ tileline singlecolor \r
1028 \r
1029     tst     r9, #0x0800\r
1030     beq     .dw_TileNorm\r
1031 \r
1032     @ (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r0: helper pattern\r
1033     TileFlip r0\r
1034     b       .dwloop\r
1035 \r
1036 .dw_TileNorm:\r
1037     TileNorm r0\r
1038     b       .dwloop\r
1039 \r
1040 .dw_SingleColor:\r
1041     and     r4, r0, r2         @ #0x0000000f\r
1042     orr     r4, r3, r4\r
1043     orr     r4, r4, r4, lsl #8\r
1044     orr     r4, r4, r4, lsl #16\r
1045     mov     r5, r4\r
1046     stmia   r1!, {r4,r5}\r
1047     b       .dwloop_nor1       @ we incremeted r1 ourselves\r
1048 \r
1049 .dw_shadow:\r
1050     tst     r6, #1             @ hi pri?\r
1051     orreq   r3, r3, #0x40\r
1052     beq     .dw_shadow_done\r
1053     ldr     r4, [r1]\r
1054     tst     r4, #0x00000080\r
1055     biceq   r4, r4, #0x000000c0\r
1056     tst     r4, #0x00008000\r
1057     biceq   r4, r4, #0x0000c000\r
1058     tst     r4, #0x00800000\r
1059     biceq   r4, r4, #0x00c00000\r
1060     tst     r4, #0x80000000\r
1061     biceq   r4, r4, #0xc0000000\r
1062     str     r4, [r1]\r
1063     ldr     r4, [r1,#4]\r
1064     tst     r4, #0x00000080\r
1065     biceq   r4, r4, #0x000000c0\r
1066     tst     r4, #0x00008000\r
1067     biceq   r4, r4, #0x0000c000\r
1068     tst     r4, #0x00800000\r
1069     biceq   r4, r4, #0x00c00000\r
1070     tst     r4, #0x80000000\r
1071     biceq   r4, r4, #0xc0000000\r
1072     str     r4, [r1,#4]\r
1073     b       .dw_shadow_done\r
1074 \r
1075 .dwloop_end:\r
1076     ldr     r0, =rendstatus\r
1077     ldr     r1, [r0]\r
1078     and     r6, r6, #2\r
1079     orr     r1, r1, r6\r
1080     str     r1, [r0]\r
1081 \r
1082     ldmfd   sp!, {r4-r11,r12}\r
1083     bx      r12\r
1084 \r
1085 \r
1086 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
1087 \r
1088 \r
1089 @ hilights 2 pixels in RGB444/BGR444 format\r
1090 .macro TileDoShHi2Pixels444 reg\r
1091     mov     \reg, \reg, ror #12\r
1092     adds    \reg, \reg, #0x40000000\r
1093     orrcs   \reg, \reg, #0xf0000000\r
1094     mov     \reg, \reg, ror #28\r
1095     adds    \reg, \reg, #0x40000000\r
1096     orrcs   \reg, \reg, #0xf0000000\r
1097     mov     \reg, \reg, ror #28\r
1098     adds    \reg, \reg, #0x40000000\r
1099     orrcs   \reg, \reg, #0xf0000000\r
1100     mov     \reg, \reg, ror #24\r
1101     adds    \reg, \reg, #0x40000000\r
1102     orrcs   \reg, \reg, #0xf0000000\r
1103     mov     \reg, \reg, ror #28\r
1104     adds    \reg, \reg, #0x40000000\r
1105     orrcs   \reg, \reg, #0xf0000000\r
1106     mov     \reg, \reg, ror #28\r
1107     adds    \reg, \reg, #0x40000000\r
1108     orrcs   \reg, \reg, #0xf0000000\r
1109     mov     \reg, \reg, ror #12\r
1110 .endm\r
1111 \r
1112 \r
1113 .global FinalizeLineBGR444 @ int sh\r
1114 \r
1115 FinalizeLineBGR444:\r
1116     stmfd   sp!, {r4-r6,lr}\r
1117     mov     r6, r0\r
1118     ldr     lr, =(Pico+0x22228)  @ Pico.video\r
1119     ldr     r0, =DrawLineDest\r
1120     ldrb    r12, [lr, #12]\r
1121     ldr     r0, [r0]\r
1122     sub     r3, lr, #0x128       @ r3=Pico.cram\r
1123 \r
1124     tst     r12, #1\r
1125     movne   r2, #320/4           @ len\r
1126     bne     .fl_no32colBGR444\r
1127     ldr     r4, =PicoOpt\r
1128     mov     r2, #256/4\r
1129     ldr     r4, [r4]\r
1130     tst     r4, #0x100\r
1131     addeq   r0, r0, #32*2\r
1132 \r
1133 .fl_no32colBGR444:\r
1134     tst     r6, r6\r
1135     beq     .fl_noshBGR444\r
1136 \r
1137     ldr     r4, =HighPal\r
1138 \r
1139     ldrb    r12, [lr, #-0x1a]      @ 0x2220e ~ dirtyPal\r
1140     tst     r12, r12\r
1141     moveq   r3, r4\r
1142     beq     .fl_noshBGR444\r
1143     mov     r12, #0\r
1144     strb    r12, [lr, #-0x1a]\r
1145 \r
1146     mov     lr, #0x40/8\r
1147     @ copy pal:\r
1148 .fl_loopcpBGR444:\r
1149     ldmia   r3!, {r1,r5,r6,r12}\r
1150     subs    lr, lr, #1\r
1151     stmia   r4!, {r1,r5,r6,r12}\r
1152     bne     .fl_loopcpBGR444\r
1153 \r
1154     @ shadowed pixels:\r
1155     mov     r12,    #0x0077\r
1156     orr     r12,r12,#0x0700\r
1157     orr     r12,r12,r12,lsl #16\r
1158     sub     r3, r3, #0x40*2\r
1159     add     r5, r4, #0x80*2\r
1160     mov     lr, #0x40/4\r
1161 .fl_loopcpBGR444_sh:\r
1162     ldmia   r3!, {r1,r6}\r
1163     subs    lr, lr, #1\r
1164     and     r1, r12, r1, lsr #1\r
1165     and     r6, r12, r6, lsr #1\r
1166     stmia   r4!, {r1,r6}\r
1167     stmia   r5!, {r1,r6}\r
1168     bne     .fl_loopcpBGR444_sh\r
1169 \r
1170     @ hilighted pixels:\r
1171     sub     r3, r3, #0x40*2\r
1172     mov     lr, #0x40/2\r
1173 .fl_loopcpBGR444_hi:\r
1174     ldr     r1, [r3], #4\r
1175     TileDoShHi2Pixels444 r1\r
1176     str     r1, [r4], #4\r
1177     subs    lr, lr, #1\r
1178     bne     .fl_loopcpBGR444_hi\r
1179 \r
1180     sub     r3, r4, #0x40*3*2\r
1181 \r
1182 \r
1183 .fl_noshBGR444:\r
1184     ldr     r1, =(HighCol+8)\r
1185     mov     lr, #0xff\r
1186     mov     lr, lr, lsl #1\r
1187 \r
1188 .fl_loopBGR444:\r
1189 \r
1190     ldr     r12, [r1], #4\r
1191     subs    r2, r2, #1\r
1192 \r
1193     and     r4, lr, r12, lsl #1\r
1194     ldrh    r4, [r3, r4]\r
1195     and     r5, lr, r12, lsr #7\r
1196     ldrh    r5, [r3, r5]\r
1197     and     r6, lr, r12, lsr #15\r
1198     ldrh    r6, [r3, r6]\r
1199     orr     r4, r4, r5, lsl #16\r
1200 \r
1201     and     r5, lr, r12, lsr #23\r
1202     ldrh    r5, [r3, r5]              @ 2c.i.\r
1203     orr     r5, r6, r5, lsl #16\r
1204 \r
1205     stmia   r0!, {r4,r5}\r
1206     bne     .fl_loopBGR444\r
1207 \r
1208 \r
1209     ldmfd   sp!, {r4-r6,lr}\r
1210     bx lr\r
1211 \r
1212 \r
1213 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
1214 \r
1215 \r
1216 @ hilights 2 pixels in RGB555/BGR555 format\r
1217 .macro TileDoShHi2Pixels555 reg\r
1218     adds    \reg, \reg, #0x40000000\r
1219     orrcs   \reg, \reg, #0xf0000000\r
1220     mov     \reg, \reg, ror #27\r
1221     adds    \reg, \reg, #0x40000000\r
1222     orrcs   \reg, \reg, #0xf0000000\r
1223     mov     \reg, \reg, ror #26\r
1224     adds    \reg, \reg, #0x40000000\r
1225     orrcs   \reg, \reg, #0xf0000000\r
1226     mov     \reg, \reg, ror #27\r
1227     adds    \reg, \reg, #0x40000000\r
1228     orrcs   \reg, \reg, #0xf0000000\r
1229     mov     \reg, \reg, ror #27\r
1230     adds    \reg, \reg, #0x40000000\r
1231     orrcs   \reg, \reg, #0xf0000000\r
1232     mov     \reg, \reg, ror #26\r
1233     adds    \reg, \reg, #0x40000000\r
1234     orrcs   \reg, \reg, #0xf0000000\r
1235     mov     \reg, \reg, ror #27\r
1236 .endm\r
1237 \r
1238 \r
1239 @ Convert 0000bbb0 ggg0rrr0\r
1240 @ to      rrrrrggg gggbbbbb\r
1241 \r
1242 @ r2,r3,r9 - scratch, lr = 0x001c001c, r8 = 0x00030003\r
1243 .macro convRGB565 reg\r
1244     and     r2,   lr,   \reg,lsl #1\r
1245     and     r9,   r8,   \reg,lsr #2\r
1246     orr     r2,   r2,   r9           @ r2=red\r
1247     and     r3,   lr,   \reg,lsr #7\r
1248     and     r9,   r8,   \reg,lsr #10\r
1249     orr     r3,   r3,   r9           @ r3=blue\r
1250     and     \reg, \reg, lr,  lsl #3\r
1251     orr     \reg, \reg, \reg,lsl #3  @ green\r
1252     orr     \reg, \reg, r2,  lsl #11 @ add red back\r
1253     orr     \reg, \reg, r3           @ add blue back\r
1254 .endm\r
1255 \r
1256 vidConvCpyRGB565: @ void *to, void *from, int pixels\r
1257     stmfd   sp!, {r4-r9,lr}\r
1258 \r
1259     mov     r12, r2, lsr #3 @ repeats\r
1260     mov     lr, #0x001c0000\r
1261     orr     lr, lr,  #0x01c  @ lr == pattern 0x001c001c\r
1262     mov     r8, #0x00030000\r
1263     orr     r8, r8,  #0x003  @ lr == pattern 0x001c001c\r
1264 \r
1265 .loopRGB565:\r
1266     ldmia   r1!, {r4-r7}\r
1267     subs    r12, r12, #1\r
1268     convRGB565 r4\r
1269     str     r4, [r0], #4\r
1270     convRGB565 r5\r
1271     str     r5, [r0], #4\r
1272     convRGB565 r6\r
1273     str     r6, [r0], #4\r
1274     convRGB565 r7\r
1275     str     r7, [r0], #4\r
1276 \r
1277     bgt     .loopRGB565\r
1278 \r
1279     ldmfd   sp!, {r4-r9,lr}\r
1280     bx      lr\r
1281 \r
1282 \r
1283 \r
1284 .global FinalizeLineRGB555 @ int sh\r
1285 \r
1286 FinalizeLineRGB555:\r
1287     stmfd   sp!, {r4-r8,lr}\r
1288     ldr     r5, =(Pico+0x22228)  @ Pico.video\r
1289     ldr     r4, =HighPal\r
1290 \r
1291     ldrb    r7, [r5, #-0x1a]     @ 0x2220e ~ dirtyPal\r
1292     mov     r6, r0\r
1293     mov     r1, #0\r
1294     tst     r7, r7\r
1295     beq     .fl_noconvRGB555\r
1296     strb    r1, [r5, #-0x1a]\r
1297     sub     r1, r5, #0x128       @ r1=Pico.cram\r
1298     mov     r0, r4\r
1299     mov     r2, #0x40\r
1300     bl      vidConvCpyRGB565\r
1301 \r
1302 .fl_noconvRGB555:\r
1303     ldrb    r12, [r5, #12]\r
1304     ldr     r0, =DrawLineDest\r
1305     ldr     r0, [r0]\r
1306 \r
1307     tst     r12, #1\r
1308     movne   r2, #320/8           @ len\r
1309     bne     .fl_no32colRGB555\r
1310     ldr     r3, =PicoOpt\r
1311     mov     r2, #256/8\r
1312     ldr     r3, [r3]\r
1313     tst     r3, #0x100\r
1314     addeq   r0, r0, #32*2\r
1315 \r
1316 .fl_no32colRGB555:\r
1317     mov     r3, r4\r
1318     tst     r6, r6\r
1319     beq     .fl_noshRGB555\r
1320     tst     r7, r7\r
1321     beq     .fl_noshRGB555\r
1322 \r
1323     @ shadowed pixels:\r
1324     mov     r12,    #0x008e\r
1325     orr     r12,r12,#0x7300\r
1326     orr     r12,r12,r12,lsl #16\r
1327     add     r4, r3, #0x40*2\r
1328     add     r5, r3, #0xc0*2\r
1329     mov     lr, #0x40/4\r
1330 .fl_loopcpRGB555_sh:\r
1331     ldmia   r3!, {r1,r6}\r
1332     subs    lr, lr, #1\r
1333     and     r1, r12, r1, lsr #1\r
1334     and     r6, r12, r6, lsr #1\r
1335     stmia   r4!, {r1,r6}\r
1336     stmia   r5!, {r1,r6}\r
1337     bne     .fl_loopcpRGB555_sh\r
1338 \r
1339     @ hilighted pixels:\r
1340     sub     r3, r3, #0x40*2\r
1341     mov     lr, #0x40/2\r
1342 .fl_loopcpRGB555_hi:\r
1343     ldr     r1, [r3], #4\r
1344     TileDoShHi2Pixels555 r1\r
1345     str     r1, [r4], #4\r
1346     subs    lr, lr, #1\r
1347     bne     .fl_loopcpRGB555_hi\r
1348 \r
1349     sub     r3, r3, #0x40*2\r
1350 \r
1351 \r
1352 .fl_noshRGB555:\r
1353     ldr     r1, =(HighCol+8)\r
1354     mov     lr, #0xff\r
1355     mov     lr, lr, lsl #1\r
1356 \r
1357 .fl_loopRGB555:\r
1358 \r
1359     ldr     r12, [r1], #4\r
1360     ldr     r7,  [r1], #4\r
1361 \r
1362     and     r4, lr, r12, lsl #1\r
1363     ldrh    r4, [r3, r4]\r
1364     and     r5, lr, r12, lsr #7\r
1365     ldrh    r5, [r3, r5]\r
1366     and     r6, lr, r12, lsr #15\r
1367     ldrh    r6, [r3, r6]\r
1368     orr     r4, r4, r5, lsl #16\r
1369 \r
1370     and     r5, lr, r12, lsr #23\r
1371     ldrh    r5, [r3, r5]\r
1372     and     r8, lr, r7, lsl #1\r
1373     ldrh    r8, [r3, r8]\r
1374     orr     r5, r6, r5, lsl #16\r
1375 \r
1376     and     r6, lr, r7, lsr #7\r
1377     ldrh    r6, [r3, r6]\r
1378     and     r12,lr, r7, lsr #15\r
1379     ldrh    r12,[r3, r12]\r
1380     orr     r8, r8, r6, lsl #16\r
1381 \r
1382     and     r6, lr, r7, lsr #23\r
1383     ldrh    r6, [r3, r6]             @ 1 cycle interlock here (r6)\r
1384     subs    r2, r2, #1\r
1385     orr     r12,r12, r6, lsl #16\r
1386 \r
1387     stmia   r0!, {r4,r5,r8,r12}\r
1388     bne     .fl_loopRGB555\r
1389 \r
1390 \r
1391     ldmfd   sp!, {r4-r8,lr}\r
1392     bx lr\r
1393 \r
1394 @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
1395 \r
1396 @ utility\r
1397 .global blockcpy @ void *dst, void *src, size_t n\r
1398 \r
1399 blockcpy:\r
1400     stmfd   sp!, {r4,r5}\r
1401     mov     r2, r2, lsr #4\r
1402 blockcpy_loop:\r
1403     ldmia   r1!, {r3-r5,r12}\r
1404     subs    r2, r2, #1\r
1405     stmia   r0!, {r3-r5,r12}\r
1406     bne     blockcpy_loop\r
1407     ldmfd   sp!, {r4,r5}\r
1408     bx      lr\r
1409 \r
1410 \r
1411 .global blockcpy_or @ void *dst, void *src, size_t n, int pat\r
1412 \r
1413 blockcpy_or:\r
1414     stmfd   sp!, {r4-r6}\r
1415     orr     r3, r3, r3, lsl #8\r
1416     orr     r3, r3, r3, lsl #16\r
1417     mov     r2, r2, lsr #4\r
1418 blockcpy_loop_or:\r
1419     ldmia   r1!, {r4-r6,r12}\r
1420     subs    r2, r2, #1\r
1421     orr     r4, r4, r3\r
1422     orr     r5, r5, r3\r
1423     orr     r6, r6, r3\r
1424     orr     r12,r12,r3\r
1425     stmia   r0!, {r4-r6,r12}\r
1426     bne     blockcpy_loop_or\r
1427     ldmfd   sp!, {r4-r6}\r
1428     bx      lr\r
1429 \r