split memories away from Pico
[picodrive.git] / pico / draw2_arm.S
1 /*\r
2  * assembly optimized versions of most funtions from draw2.c\r
3  * (C) notaz, 2006-2008\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 @ define these constants in your include file:\r
14 @ .equiv START_ROW,             1\r
15 @ .equiv END_ROW,               27\r
16 @ one row means 8 pixels. If above example was used, (27-1)*8=208 lines would be rendered.\r
17 #ifndef START_ROW\r
18 #define START_ROW 0\r
19 #endif\r
20 #ifndef END_ROW\r
21 #define END_ROW 28\r
22 #endif\r
23 \r
24 .text\r
25 .align 2\r
26 \r
27 @ void BackFillFull(void *dst, int reg7)\r
28 \r
29 .global BackFillFull\r
30 \r
31 BackFillFull:\r
32     stmfd   sp!, {r4-r9,lr}\r
33 \r
34     add     lr, r0, #328*8\r
35     mov     r0, r1, lsl #26\r
36     mov     r0, r0, lsr #26\r
37 \r
38     orr     r0, r0, r0, lsl #8\r
39     orr     r0, r0, r0, lsl #16\r
40 \r
41     mov     r1, r0 @ 25 opcodes wasted?\r
42     mov     r2, r0\r
43     mov     r3, r0\r
44     mov     r4, r0\r
45     mov     r5, r0\r
46     mov     r6, r0\r
47     mov     r7, r0\r
48     mov     r8, r0\r
49     mov     r9, r0\r
50 \r
51     mov     r12, #(END_ROW-START_ROW)*8\r
52 \r
53     @ go go go!\r
54 .bff_loop:\r
55     add     lr, lr, #8\r
56     subs    r12, r12, #1\r
57 \r
58     stmia   lr!, {r0-r9} @ 10*4*8\r
59     stmia   lr!, {r0-r9}\r
60     stmia   lr!, {r0-r9}\r
61     stmia   lr!, {r0-r9}\r
62     stmia   lr!, {r0-r9}\r
63     stmia   lr!, {r0-r9}\r
64     stmia   lr!, {r0-r9}\r
65     stmia   lr!, {r0-r9}\r
66 \r
67     bne     .bff_loop\r
68 \r
69     ldmfd   sp!, {r4-r9,lr}\r
70     bx      lr\r
71 \r
72 .pool\r
73 \r
74 @ -------- some macros --------\r
75 \r
76 \r
77 @ helper\r
78 @ TileLineSinglecol (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r0: pixels8_old\r
79 .macro TileLineSinglecol notsinglecol=0\r
80     and     r2, r2, #0xf        @ #0x0000000f\r
81 .if !\notsinglecol\r
82     cmp     r2, r0, lsr #28     @ if these don't match,\r
83     bicne   r9, r9, #2          @ it is a sign that whole tile is not singlecolor (only it's lines may be)\r
84 .endif\r
85     orr     r4, r3, r2\r
86     orr     r4, r4, r4, lsl #8\r
87 \r
88     tst     r1, #1              @ not aligned?\r
89     strneb  r4, [r1], #1\r
90     streqh  r4, [r1], #2\r
91     strh    r4, [r1], #2\r
92     strh    r4, [r1], #2\r
93     strh    r4, [r1], #2\r
94     strneb  r4, [r1], #1        @ have a remaining unaligned pixel?\r
95     sub     r1, r1, #8\r
96 .if !\notsinglecol\r
97     mov     r0, #0xf\r
98     orr     r0, r0, r2, lsl #28 @ we will need the old palindex later\r
99 .endif\r
100 .endm\r
101 \r
102 @ TileNorm (r1=pdest, r2=pixels8, r3=pal) r0,r4: scratch\r
103 .macro TileLineNorm\r
104     ands    r4, r0, r2, lsr #12 @ #0x0000f000\r
105     orrne   r4, r3, r4\r
106     strneb  r4, [r1]\r
107     ands    r4, r0, r2, lsr #8  @ #0x00000f00\r
108     orrne   r4, r3, r4\r
109     strneb  r4, [r1,#1]\r
110     ands    r4, r0, r2, lsr #4  @ #0x000000f0\r
111     orrne   r4, r3, r4\r
112     strneb  r4, [r1,#2]\r
113     ands    r4, r0, r2          @ #0x0000000f\r
114     orrne   r4, r3, r4\r
115     strneb  r4, [r1,#3]\r
116     ands    r4, r0, r2, lsr #28 @ #0xf0000000\r
117     orrne   r4, r3, r4\r
118     strneb  r4, [r1,#4]\r
119     ands    r4, r0, r2, lsr #24 @ #0x0f000000\r
120     orrne   r4, r3, r4\r
121     strneb  r4, [r1,#5]\r
122     ands    r4, r0, r2, lsr #20 @ #0x00f00000\r
123     orrne   r4, r3, r4\r
124     strneb  r4, [r1,#6]\r
125     ands    r4, r0, r2, lsr #16 @ #0x000f0000\r
126     orrne   r4, r3, r4\r
127     strneb  r4, [r1,#7]\r
128 .endm\r
129 \r
130 @ TileFlip (r1=pdest, r2=pixels8, r3=pal) r0,r4: scratch\r
131 .macro TileLineFlip\r
132     ands    r4, r0, r2, lsr #16 @ #0x000f0000\r
133     orrne   r4, r3, r4\r
134     strneb  r4, [r1]\r
135     ands    r4, r0, r2, lsr #20 @ #0x00f00000\r
136     orrne   r4, r3, r4\r
137     strneb  r4, [r1,#1]\r
138     ands    r4, r0, r2, lsr #24 @ #0x0f000000\r
139     orrne   r4, r3, r4\r
140     strneb  r4, [r1,#2]\r
141     ands    r4, r0, r2, lsr #28 @ #0xf0000000\r
142     orrne   r4, r3, r4\r
143     strneb  r4, [r1,#3]\r
144     ands    r4, r0, r2          @ #0x0000000f\r
145     orrne   r4, r3, r4\r
146     strneb  r4, [r1,#4]\r
147     ands    r4, r0, r2, lsr #4  @ #0x000000f0\r
148     orrne   r4, r3, r4\r
149     strneb  r4, [r1,#5]\r
150     ands    r4, r0, r2, lsr #8  @ #0x00000f00\r
151     orrne   r4, r3, r4\r
152     strneb  r4, [r1,#6]\r
153     ands    r4, r0, r2, lsr #12 @ #0x0000f000\r
154     orrne   r4, r3, r4\r
155     strneb  r4, [r1,#7]\r
156 .endm\r
157 \r
158 @ Tile (r1=pdest, r3=pal, r9=prevcode, r10=Pico.vram) r2,r4,r7: scratch, r0=0xf\r
159 .macro Tile hflip vflip\r
160     mov     r7, r9, lsl #13       @ r9=code<<8; addr=(code&0x7ff)<<4;\r
161     add     r7, r10, r7, lsr #16\r
162     orr     r9, r9, #3            @ emptytile=singlecolor=1, r9 must be <code_16> 00000xxx\r
163 .if \vflip\r
164     @ we read tilecodes in reverse order if we have vflip\r
165     add     r7, r7, #8*4\r
166 .endif\r
167     @ loop through 8 lines\r
168     orr     r9, r9, #(7<<24)\r
169     b       1f @ loop_enter\r
170 \r
171 0:  @ singlecol_loop\r
172     subs    r9, r9, #(1<<24)\r
173     add     r1, r1, #328          @ set pointer to next line\r
174     bmi     8f @ loop_exit with r0 restore\r
175 1:\r
176 .if \vflip\r
177     ldr     r2, [r7, #-4]!        @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
178 .else\r
179     ldr     r2, [r7], #4\r
180 .endif\r
181     tst     r2, r2\r
182     beq     2f                    @ empty line\r
183     bic     r9, r9, #1\r
184     cmp     r2, r2, ror #4\r
185     bne     3f                    @ not singlecolor\r
186     TileLineSinglecol\r
187     b       0b\r
188 \r
189 2:\r
190     bic     r9, r9, #2\r
191 2:  @ empty_loop\r
192     subs    r9, r9, #(1<<24)\r
193     add     r1, r1, #328          @ set pointer to next line\r
194     bmi     8f @ loop_exit with r0 restore\r
195 .if \vflip\r
196     ldr     r2, [r7, #-4]!        @ next pack\r
197 .else\r
198     ldr     r2, [r7], #4\r
199 .endif\r
200     mov     r0, #0xf              @ singlecol_loop might have messed r0\r
201     tst     r2, r2\r
202     beq     2b\r
203 \r
204     bic     r9, r9, #3            @ if we are here, it means we have empty and not empty line\r
205     b       5f\r
206 \r
207 3:  @ not empty, not singlecol\r
208     mov     r0, #0xf\r
209     bic     r9, r9, #3\r
210     b       6f\r
211 \r
212 4:  @ not empty, not singlecol loop\r
213     subs    r9, r9, #(1<<24)\r
214     add     r1, r1, #328          @ set pointer to next line\r
215     bmi     9f @ loop_exit\r
216 .if \vflip\r
217     ldr     r2, [r7, #-4]!        @ next pack\r
218 .else\r
219     ldr     r2, [r7], #4\r
220 .endif\r
221     tst     r2, r2\r
222     beq     4b                    @ empty line\r
223 5:\r
224     cmp     r2, r2, ror #4\r
225     beq     7f                    @ singlecolor line\r
226 6:\r
227 .if \hflip\r
228     TileLineFlip\r
229 .else\r
230     TileLineNorm\r
231 .endif\r
232     b       4b\r
233 7:\r
234     TileLineSinglecol 1\r
235     b       4b\r
236 \r
237 8:\r
238     mov     r0, #0xf\r
239 9:  @ loop_exit\r
240     add     r9, r9, #(1<<24)      @ fix r9\r
241     sub     r1, r1, #328*8        @ restore pdest pointer\r
242 .endm\r
243 \r
244 \r
245 @ TileLineSinglecolAl (r1=pdest, r4,r7=color)\r
246 .macro TileLineSinglecolAl0\r
247     stmia   r1!, {r4,r7}\r
248     add     r1, r1, #320\r
249 .endm\r
250 \r
251 .macro TileLineSinglecolAl1\r
252     strb    r4, [r1], #1\r
253     strh    r4, [r1], #2\r
254     str     r4, [r1], #4\r
255     strb    r4, [r1], #1+320\r
256 @    add     r1, r1, #320\r
257 .endm\r
258 \r
259 .macro TileLineSinglecolAl2\r
260     strh    r4, [r1], #2\r
261     str     r4, [r1], #4\r
262     strh    r4, [r1], #2\r
263     add     r1, r1, #320\r
264 .endm\r
265 \r
266 .macro TileLineSinglecolAl3\r
267     strb    r4, [r1], #1\r
268     str     r4, [r1], #4\r
269     strh    r4, [r1], #2\r
270     strb    r4, [r1], #1+320\r
271 @    add     r1, r1, #320\r
272 .endm\r
273 \r
274 @ TileSinglecol (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=0xf\r
275 @ kaligned==1, if dest is always aligned\r
276 .macro TileSinglecol kaligned=0\r
277     and     r4, r2, #0xf       @ we assume we have good r2 from previous time\r
278     orr     r4, r4, r3\r
279     orr     r4, r4, r4, lsl #8\r
280     orr     r4, r4, r4, lsl #16\r
281     mov     r7, r4\r
282 \r
283 .if !\kaligned\r
284     tst     r1, #2             @ not aligned?\r
285     bne     2f\r
286     tst     r1, #1\r
287     bne     1f\r
288 .endif\r
289 \r
290     TileLineSinglecolAl0\r
291     TileLineSinglecolAl0\r
292     TileLineSinglecolAl0\r
293     TileLineSinglecolAl0\r
294     TileLineSinglecolAl0\r
295     TileLineSinglecolAl0\r
296     TileLineSinglecolAl0\r
297     TileLineSinglecolAl0\r
298 \r
299 .if !\kaligned\r
300     b       4f\r
301 1:\r
302     TileLineSinglecolAl1\r
303     TileLineSinglecolAl1\r
304     TileLineSinglecolAl1\r
305     TileLineSinglecolAl1\r
306     TileLineSinglecolAl1\r
307     TileLineSinglecolAl1\r
308     TileLineSinglecolAl1\r
309     TileLineSinglecolAl1\r
310     b       4f\r
311 \r
312 2:\r
313     tst     r1, #1\r
314     bne     3f\r
315 \r
316     TileLineSinglecolAl2\r
317     TileLineSinglecolAl2\r
318     TileLineSinglecolAl2\r
319     TileLineSinglecolAl2\r
320     TileLineSinglecolAl2\r
321     TileLineSinglecolAl2\r
322     TileLineSinglecolAl2\r
323     TileLineSinglecolAl2\r
324     b       4f\r
325 \r
326 3:\r
327     TileLineSinglecolAl3\r
328     TileLineSinglecolAl3\r
329     TileLineSinglecolAl3\r
330     TileLineSinglecolAl3\r
331     TileLineSinglecolAl3\r
332     TileLineSinglecolAl3\r
333     TileLineSinglecolAl3\r
334     TileLineSinglecolAl3\r
335 \r
336 4:\r
337 .endif\r
338     sub     r1, r1, #328*8        @ restore pdest pointer\r
339 .endm\r
340 \r
341 \r
342 \r
343 @ DrawLayerTiles(*hcache, *scrpos, (cells<<24)|(nametab<<9)|(vscroll&0x3ff)<<11|(shift[width]<<8)|planeend, (ymask<<24)|(planestart<<16)|[htab||hscroll]\r
344 \r
345 @ void DrawLayerFull(int plane, int *hcache, int planestart, int planeend,\r
346 @                    struct PicoEState *est)\r
347 \r
348 .global DrawLayerFull\r
349 \r
350 DrawLayerFull:\r
351     ldr     r12,[sp]              @ est\r
352     stmfd   sp!, {r4-r11,lr}\r
353 \r
354     mov     r6, r1        @ hcache\r
355 \r
356     ldr     r11, [r12, #OFS_EST_Pico]\r
357     ldr     r10, [r12, #OFS_EST_PicoMem_vram]\r
358     ldrb    r5, [r11, #OFS_Pico_video_reg+13] @ pvid->reg[13]\r
359     ldrb    r7, [r11, #OFS_Pico_video_reg+11]\r
360 \r
361     sub     lr, r3, r2\r
362     and     lr, lr, #0x00ff0000   @ lr=cells\r
363 \r
364     mov     r5, r5, lsl #10       @ htab=pvid->reg[13]<<9; (halfwords)\r
365     add     r5, r5, r0, lsl #1    @ htab+=plane\r
366     bic     r5, r5, #0x00ff0000   @ just in case\r
367 \r
368     tst     r7, #3                @ full screen scroll? (if ==0)\r
369     ldrb    r7, [r11, #OFS_Pico_video_reg+16] @ ??hh??ww\r
370     ldreqh  r5, [r10, r5]\r
371     biceq   r5, r5, #0x0000fc00   @ r5=hscroll (0-0x3ff)\r
372     movne   r5, r5, lsr #1\r
373     orrne   r5, r5, #0x8000       @ this marks that we have htab pointer, not hscroll here\r
374 \r
375     and     r8, r7, #3\r
376 \r
377     orr     r5, r5, r7, lsl #1+24\r
378     orr     r5, r5, #0x1f000000\r
379     cmp     r8, #1\r
380     biclt   r5, r5, #0x80000000\r
381     biceq   r5, r5, #0xc0000000\r
382     bicgt   r5, r5, #0xe0000000\r
383 \r
384     mov     r9, r2, lsl #24\r
385     orr     r5, r5, r9, lsr #8    @ r5=(ymask<<24)|(trow<<16)|[htab||hscroll]\r
386 \r
387     add     r4, r8, #5\r
388     cmp     r4, #7\r
389     subge   r4, r4, #1            @ r4=shift[width] (5,6,6,7)\r
390 \r
391     orr     lr, lr, r4         \r
392     orr     lr, lr, r3, lsl #24   @ lr=(planeend<<24)|(cells<<16)|shift[width]\r
393 \r
394     @ calculate xmask:\r
395     mov     r8, r8, lsl #24+5\r
396     orr     r8, r8, #0x1f000000\r
397 \r
398     @ Find name table:\r
399     tst     r0, r0\r
400     ldreqb  r4, [r11, #OFS_Pico_video_reg+2]\r
401     moveq   r4, r4, lsr #3\r
402     ldrneb  r4, [r11, #OFS_Pico_video_reg+4]\r
403     and     r4, r4, #7\r
404     orr     lr, lr, r4, lsl #13   @ lr|=nametab_bits{3}<<13\r
405 \r
406     ldr     r11,[sp, #9*4]        @ est\r
407     sub     r4, r9, #(START_ROW<<24)\r
408     ldr     r11, [r11, #OFS_EST_Draw2FB]\r
409     mov     r4, r4, asr #24\r
410     mov     r7, #328*8\r
411     mla     r11, r4, r7, r11      @ scrpos+=8*328*(planestart-START_ROW);\r
412 \r
413     @ Get vertical scroll value:\r
414     add     r7, r10, #0x012000\r
415     add     r7, r7,  #0x000180    @ r7=Pico.vsram (Pico+0x22180)\r
416     ldr     r7, [r7]\r
417     tst     r0, r0\r
418     moveq   r7, r7, lsl #22\r
419     movne   r7, r7, lsl #6\r
420     mov     r7, r7, lsr #22       @ r7=vscroll (10 bits)\r
421 \r
422     orr     lr, lr, r7, lsl #3\r
423     mov     lr, lr, ror #24       @ packed: cccccccc nnnvvvvv vvvvvsss pppppppp: cells, nametab, vscroll, shift[width], planeend\r
424 \r
425     ands    r7, r7, #7\r
426     addne   lr, lr, #1            @ we have vertically clipped tiles due to vscroll, so we need 1 more row\r
427 \r
428     rsb     r7, r7, #8\r
429     str     r7, [r6], #4          @ push y-offset to tilecache\r
430     mov     r4, #328\r
431     mla     r11, r4, r7, r11      @ scrpos+=(8-(vscroll&7))*328;\r
432 \r
433     mov     r9, #0xff000000       @ r9=(prevcode<<8)|flags: 1~tile empty, 2~tile singlecolor\r
434 \r
435 .rtrloop_outer:\r
436     mov     r4, lr, lsl #11\r
437     mov     r4, r4, lsr #25     @ r4=vscroll>>3 (7 bits)\r
438     add     r4, r4, r5, lsr #16 @ +trow\r
439     and     r4, r4, r5, lsr #24 @ &=ymask\r
440     mov     r7, lr, lsr #8\r
441     and     r7, r7, #7          @ shift[width]\r
442     mov     r0, lr, lsr #9\r
443     and     r0, r0, #0x7000     @ nametab\r
444     add     r12,r0, r4, lsl r7  @ nametab_row = nametab + (((trow+(vscroll>>3))&ymask)<<shift[width]); \r
445 \r
446     mov     r4, lr, lsr #24\r
447     orr     r12,r12,r4, lsl #23\r
448     mov     r12,r12,lsl #1      @ (nametab_row|(cells<<24)) (halfword compliant)\r
449 \r
450     @ htab?\r
451     tst     r5, #0x8000\r
452     moveq   r7, r5, lsl #22 @ hscroll (0-3FFh)\r
453     moveq   r7, r7, lsr #22\r
454     beq     .rtr_hscroll_done\r
455 \r
456     @ get hscroll from htab\r
457     mov     r7, r5, lsl #17\r
458     ands    r4, r5, #0x00ff0000\r
459     add     r7, r7, r4, lsl #5  @ +=trow<<4\r
460     andne   r4, lr, #0x3800\r
461     subne   r7, r7, r4, lsl #7  @ if(trow) htaddr-=(vscroll&7)<<1;\r
462     mov     r7, r7, lsr #16     @ halfwords\r
463     ldrh    r7, [r10, r7]\r
464 \r
465 .rtr_hscroll_done:\r
466     and     r8, r8, #0xff000000\r
467     rsb     r4, r7, #0          @ r4=tilex=(-ts->hscroll)>>3\r
468     mov     r4, r4, asr #3\r
469     and     r4, r4, #0xff\r
470     orr     r8, r8, r4          @ r8=(xmask<<24)|tilex\r
471 \r
472     sub     r7, r7, #1\r
473     and     r7, r7, #7\r
474     add     r7, r7, #1      @ r7=dx=((ts->hscroll-1)&7)+1\r
475 \r
476     cmp     r7, #8\r
477     subeq   r12,r12, #0x01000000 @ we will loop cells+1 times, so loop less when there is no hscroll\r
478 \r
479     add     r1, r11, r7          @ r1=pdest\r
480     mov     r0, #0xf\r
481     b       .rtrloop_enter\r
482 \r
483     @ r4 & r7 are scratch in this loop\r
484 .rtrloop: @ 40-41 times\r
485     add     r1, r1, #8\r
486     subs    r12,r12, #0x01000000\r
487     add     r8, r8, #1\r
488     bmi     .rtrloop_exit\r
489 \r
490 .rtrloop_enter:\r
491     and     r7, r8,  r8, lsr #24\r
492     add     r7, r10, r7, lsl #1\r
493     bic     r4, r12, #0xff000000 @ Pico.vram[nametab_row+(tilex&xmask)];\r
494     ldrh    r7, [r7, r4]      @ r7=code (int, but from unsigned, no sign extend)\r
495 \r
496     tst     r7, #0x8000\r
497     bne     .rtr_hiprio\r
498 \r
499     cmp     r7, r9, lsr #8\r
500     bne     .rtr_notsamecode\r
501     @ we know stuff about this tile already\r
502     tst     r9, #1\r
503     bne     .rtrloop         @ empty tile\r
504     tst     r9, #2\r
505     bne     .rtr_singlecolor @ singlecolor tile\r
506     b       .rtr_samecode\r
507 \r
508 .rtr_notsamecode:\r
509     and     r4, r9, #0x600000\r
510     mov     r9, r7, lsl #8      @ remember new code\r
511 \r
512     @ update cram\r
513     and     r7, r7, #0x6000\r
514     mov     r3, r7, asr #9      @ r3=pal=((code&0x6000)>>9);\r
515 \r
516 .rtr_samecode:\r
517     tst     r9, #0x100000       @ vflip?\r
518     bne     .rtr_vflip\r
519 \r
520     tst     r9, #0x080000       @ hflip?\r
521     bne     .rtr_hflip\r
522 \r
523     @ Tile (r1=pdest, r3=pal, r9=prevcode, r10=Pico.vram) r2,r4,r7: scratch, r0=0xf\r
524     Tile 0, 0\r
525     b       .rtrloop\r
526 \r
527 .rtr_hflip:\r
528     Tile 1, 0\r
529     b       .rtrloop\r
530 \r
531 .rtr_vflip:\r
532     tst     r9, #0x080000       @ hflip?\r
533     bne     .rtr_vflip_hflip\r
534 \r
535     Tile 0, 1\r
536     b       .rtrloop\r
537 \r
538 .rtr_vflip_hflip:\r
539     Tile 1, 1\r
540     b       .rtrloop\r
541 \r
542 .rtr_singlecolor:\r
543     TileSinglecol\r
544     b       .rtrloop\r
545 \r
546 .rtr_hiprio:\r
547     @ *(*hcache)++ = code|(dx<<16)|(trow<<27);\r
548     sub     r4, r1, r11\r
549     orr     r7, r7, r4, lsl #16\r
550     and     r4, r5, #0x00ff0000\r
551     orr     r7, r7, r4, lsl #11 @ (trow<<27)\r
552     str     r7, [r6], #4    @ cache hi priority tile\r
553     b       .rtrloop\r
554 \r
555 .rtrloop_exit:\r
556     add     r5, r5, #0x00010000\r
557     mov     r4, r5, lsl #8\r
558     cmp     r4, lr, lsl #24\r
559     bge     .rtrloop_outer_exit\r
560     add     r11, r11, #328*8\r
561     b       .rtrloop_outer\r
562 \r
563 .rtrloop_outer_exit:\r
564 \r
565     @ terminate cache list\r
566     mov     r0, #0\r
567     str     r0, [r6]    @ save cache pointer\r
568 \r
569     ldmfd   sp!, {r4-r11,lr}\r
570     bx      lr\r
571 \r
572 .pool\r
573 \r
574 \r
575 @ void DrawTilesFromCacheF(int *hc, struct PicoEState *est)\r
576 \r
577 .global DrawTilesFromCacheF\r
578 \r
579 DrawTilesFromCacheF:\r
580     stmfd   sp!, {r4-r10,lr}\r
581 \r
582     mov     r9, #0xff000000 @ r9=prevcode=-1\r
583     mvn     r6, #0          @ r6=prevy=-1\r
584 \r
585     ldr     r4, [r1, #OFS_EST_Draw2FB]\r
586     ldr     r2, [r0], #4    @ read y offset\r
587     mov     r7, #328\r
588     mla     r2, r7, r2, r4\r
589     sub     r12, r2, #(328*8*START_ROW) @ r12=scrpos\r
590 \r
591     ldr     r10, [r1, #OFS_EST_PicoMem_vram]\r
592     mov     r8, r0               @ hc\r
593     mov     r0, #0xf\r
594 \r
595     @ scratch: r4, r7\r
596         @ *hcache++ = code|(dx<<16)|(trow<<27); // cache it\r
597 \r
598 .dtfcf_loop:\r
599     ldr     r7, [r8], #4    @ read code\r
600     movs    r1, r7, lsr #16 @ r1=dx;\r
601     ldmeqfd sp!, {r4-r10,pc} @ dx is never zero, this must be a terminator, return\r
602 \r
603     @ row changed?\r
604     cmp     r6, r7, lsr #27\r
605     movne   r6, r7, lsr #27\r
606     movne   r4, #328*8\r
607     mlane   r5, r4, r6, r12 @ r5=pd = scrpos + prevy*328*8\r
608 \r
609     bic     r1, r1, #0xf800\r
610     add     r1, r5, r1      @ r1=pdest (halfwords)\r
611 \r
612     mov     r7, r7, lsl #16\r
613     mov     r7, r7, lsr #16\r
614 \r
615     cmp     r7, r9, lsr #8\r
616     bne     .dtfcf_notsamecode\r
617     @ we know stuff about this tile already\r
618     tst     r9, #1\r
619     bne     .dtfcf_loop         @ empty tile\r
620     tst     r9, #2\r
621     bne     .dtfcf_singlecolor  @ singlecolor tile\r
622     b       .dtfcf_samecode\r
623 \r
624 .dtfcf_notsamecode:\r
625     and     r4, r9, #0x600000\r
626     mov     r9, r7, lsl #8      @ remember new code\r
627 \r
628     @ update cram val\r
629     and     r7, r7, #0x6000\r
630     mov     r3, r7, asr #9      @ r3=pal=((code&0x6000)>>9);\r
631 \r
632 \r
633 .dtfcf_samecode:\r
634 \r
635     tst     r9, #0x100000       @ vflip?\r
636     bne     .dtfcf_vflip\r
637 \r
638     tst     r9, #0x080000       @ hflip?\r
639     bne     .dtfcf_hflip\r
640 \r
641     @ Tile (r1=pdest, r3=pal, r9=prevcode, r10=Pico.vram) r2,r4,r7: scratch, r0=0xf\r
642     Tile 0, 0\r
643     b       .dtfcf_loop\r
644 \r
645 .dtfcf_hflip:\r
646     Tile 1, 0\r
647     b       .dtfcf_loop\r
648 \r
649 .dtfcf_vflip:\r
650     tst     r9, #0x080000       @ hflip?\r
651     bne     .dtfcf_vflip_hflip\r
652 \r
653     Tile 0, 1\r
654     b       .dtfcf_loop\r
655 \r
656 .dtfcf_vflip_hflip:\r
657     Tile 1, 1\r
658     b       .dtfcf_loop\r
659 \r
660 .dtfcf_singlecolor:\r
661     TileSinglecol\r
662     b       .dtfcf_loop\r
663 \r
664 .pool\r
665 \r
666 \r
667 @ @@@@@@@@@@@@@@@\r
668 \r
669 @ (tile_start<<16)|row_start\r
670 @ void DrawWindowFull(int start, int end, int prio, struct PicoEState *est)\r
671 \r
672 .global DrawWindowFull\r
673 \r
674 DrawWindowFull:\r
675     stmfd   sp!, {r4-r11,lr}\r
676 \r
677     ldr     r11, [r3, #OFS_EST_Pico]\r
678     ldrb    r12, [r11, #OFS_Pico_video_reg+3] @ pvid->reg[3]\r
679     mov     r12, r12, lsl #10\r
680 \r
681     ldr     r4, [r11, #OFS_Pico_video_reg+12]\r
682     mov     r5, #1                @ nametab_step\r
683     tst     r4, #1                @ 40 cell mode?\r
684     andne   r12, r12, #0xf000     @ 0x3c<<10\r
685     andeq   r12, r12, #0xf800\r
686     movne   r5, r5, lsl #7\r
687     moveq   r5, r5, lsl #6        @ nametab_step\r
688 \r
689     and     r4, r0, #0xff\r
690     mla     r12, r5, r4, r12      @ nametab += nametab_step*start;\r
691 \r
692     ldr     r10, [r3, #OFS_EST_PicoMem_vram]\r
693     mov     r4, r0, lsr #16       @ r4=start_cell_h\r
694     add     r7, r12, r4, lsl #1\r
695 \r
696     @ fetch the first code now\r
697     ldrh    r7, [r10, r7]\r
698     cmp     r2, r7, lsr #15\r
699     ldmnefd sp!, {r4-r11,pc}      @ hack: simply assume that whole window uses same priority\r
700 \r
701     rsb     r8, r4, r1, lsr #16   @ cells (h)\r
702     orr     r8, r8, r4, lsl #8\r
703     mov     r4, r1, lsl #24\r
704     sub     r4, r4, r0, lsl #24\r
705     orr     r8, r8, r4, lsr #8    @ r8=cells_h|(start_cell_h<<8)|(cells_v<<16)\r
706     sub     r8, r8, #0x010000     @ adjust for algo\r
707 \r
708     mov     r9, #0xff000000       @ r9=prevcode=-1\r
709 \r
710     ldr     r11, [r3, #OFS_EST_Draw2FB]\r
711     and     r4, r0, #0xff\r
712     add     r11, r11, #328*8\r
713     sub     r4, r4, #START_ROW\r
714     add     r11, r11, #8\r
715 \r
716     mov     r7, #328*8\r
717     mla     r11, r7, r4, r11      @ scrpos+=8*328*(start-START_ROW);\r
718     mov     r0, #0xf\r
719 \r
720 .dwfloop_outer:\r
721     and     r6, r8, #0xff00       @ r6=tilex\r
722     add     r1, r11, r6, lsr #5   @ r1=pdest\r
723     add     r6, r12, r6, lsr #7\r
724     add     r6, r10, r6           @ r6=Pico.vram+nametab+tilex\r
725     orr     r8, r8, r8, lsl #24\r
726     sub     r8, r8, #0x01000000   @ cell loop counter\r
727     b       .dwfloop_enter\r
728 \r
729     @ r4 & r7 are scratch in this loop\r
730 .dwfloop:\r
731     add     r1, r1, #8\r
732     subs    r8, r8, #0x01000000\r
733     bmi     .dwfloop_exit\r
734 \r
735 .dwfloop_enter:\r
736     ldrh    r7, [r6], #2      @ r7=code\r
737 \r
738     cmp     r7, r9, lsr #8\r
739     bne     .dwf_notsamecode\r
740     @ we know stuff about this tile already\r
741     tst     r9, #1\r
742     bne     .dwfloop         @ empty tile\r
743     tst     r9, #2\r
744     bne     .dwf_singlecolor @ singlecolor tile\r
745     b       .dwf_samecode\r
746 \r
747 .dwf_notsamecode:\r
748     and     r4, r9, #0x600000\r
749     mov     r9, r7, lsl #8      @ remember new code\r
750 \r
751     @ update cram val\r
752     and     r7, r7, #0x6000\r
753     mov     r3, r7, asr #9      @ r3=pal=((code&0x6000)>>9);\r
754 \r
755 .dwf_samecode:\r
756 \r
757     tst     r9, #0x100000       @ vflip?\r
758     bne     .dwf_vflip\r
759 \r
760     tst     r9, #0x080000       @ hflip?\r
761     bne     .dwf_hflip\r
762 \r
763     @ Tile (r1=pdest, r3=pal, r9=prevcode, r10=PicoMem.vram)\r
764     @ r2,r4,r7: scratch, r0=0xf\r
765     Tile 0, 0\r
766     b       .dwfloop\r
767 \r
768 .dwf_hflip:\r
769     Tile 1, 0\r
770     b       .dwfloop\r
771 \r
772 .dwf_vflip:\r
773     tst     r9, #0x080000       @ hflip?\r
774     bne     .dwf_vflip_hflip\r
775 \r
776     Tile 0, 1\r
777     b       .dwfloop\r
778 \r
779 .dwf_vflip_hflip:\r
780     Tile 1, 1\r
781     b       .dwfloop\r
782 \r
783 .dwf_singlecolor:\r
784     TileSinglecol 1\r
785     b       .dwfloop\r
786 \r
787 .dwfloop_exit:\r
788     bic     r8, r8, #0xff000000  @ fix r8\r
789     subs    r8, r8, #0x010000\r
790     ldmmifd sp!, {r4-r11,pc}\r
791     add     r11, r11, #328*8\r
792     add     r12, r12, r5         @ nametab+=nametab_step\r
793     b       .dwfloop_outer\r
794 \r
795 .pool\r
796 \r
797 \r
798 @ ---------------- sprites ---------------\r
799 \r
800 .macro SpriteLoop hflip vflip\r
801 .if \vflip\r
802     mov     r1, r5, lsr #24       @ height\r
803     mov     r0, #328*8\r
804     mla     r11, r1, r0, r11      @ scrpos+=height*328*8;\r
805     add     r12, r12, r1, lsl #3  @ sy+=height*8\r
806 .endif\r
807     mov     r0, #0xf\r
808 .if \hflip\r
809     and     r1, r5, #0xff\r
810     add     r8, r8, r1, lsl #3    @ sx+=width*8\r
811 58:\r
812     cmp     r8, #336\r
813     blt     51f\r
814     add     r9, r9, r5, lsr #16\r
815     sub     r5, r5, #1            @ sub width\r
816     sub     r8, r8, #8\r
817     b       58b\r
818 .else\r
819     cmp     r8, #0                @ skip tiles hidden on the left of screen\r
820     bgt     51f\r
821 58:\r
822     add     r9, r9, r5, lsr #16\r
823     sub     r5, r5, #1\r
824     adds    r8, r8, #8\r
825     ble     58b\r
826     b       51f\r
827 .endif\r
828 \r
829 50: @ outer\r
830 .if !\hflip\r
831     add     r8, r8, #8          @ sx+=8\r
832 .endif\r
833     bic     r5, r5, #0xff000000 @ fix height\r
834     orr     r5, r5, r5, lsl #16\r
835 \r
836 51: @ outer_enter\r
837     sub     r5, r5, #1          @ width--\r
838     movs    r1, r5, lsl #24\r
839     ldmmifd sp!, {r4-r11,pc}    @ end of tile\r
840 .if \hflip\r
841     subs    r8, r8, #8          @ sx-=8\r
842     ldmlefd sp!, {r4-r11,pc}    @ tile offscreen\r
843 .else\r
844     cmp     r8, #328\r
845     ldmgefd sp!, {r4-r11,pc}    @ tile offscreen\r
846 .endif\r
847     mov     r6, r12             @ r6=sy\r
848     add     r1, r11, r8         @ pdest=scrpos+sx\r
849     b       53f\r
850 \r
851 52: @ inner\r
852     add     r9, r9, #1<<8       @ tile++\r
853 .if !\vflip\r
854     add     r6, r6, #8          @ sy+=8\r
855     add     r1, r1, #328*8\r
856 .endif\r
857 \r
858 53: @ inner_enter\r
859     @ end of sprite?\r
860     subs    r5, r5, #0x01000000\r
861     bmi     50b                 @ ->outer\r
862 .if \vflip\r
863     sub     r6, r6, #8          @ sy-=8\r
864     sub     r1, r1, #328*8\r
865 .endif\r
866 \r
867     @ offscreen?\r
868     cmp     r6, #(START_ROW*8)\r
869     ble     52b\r
870 \r
871     cmp     r6, #(END_ROW*8+8)\r
872     bge     52b\r
873 \r
874     @ Tile (r1=pdest, r3=pal, r9=prevcode, r10=PicoMem.vram)\r
875     @ r2,r4,r7: scratch, r0=0xf\r
876     Tile \hflip, \vflip\r
877     b       52b\r
878 .endm\r
879 \r
880 @ void DrawSpriteFull(unsigned int *sprite, struct PicoEState *est)\r
881 \r
882 .global DrawSpriteFull\r
883 \r
884 DrawSpriteFull:\r
885     stmfd   sp!, {r4-r11,lr}\r
886 \r
887     ldr     r3, [r0]        @ sprite[0]\r
888     mov     r5, r3, lsl #4\r
889     mov     r6, r5, lsr #30\r
890     add     r6, r6, #1      @ r6=width\r
891     mov     r5, r5, lsl #2\r
892     mov     r5, r5, lsr #30\r
893     add     r5, r5, #1      @ r5=height\r
894 \r
895     mov     r12, r3,  lsl #23\r
896     mov     r12, r12, lsr #23\r
897 \r
898     ldr     lr, [r0, #4]    @ lr=code\r
899     sub     r12, r12, #0x78 @ r12=sy\r
900     mov     r8, lr, lsl #7\r
901     mov     r8, r8, lsr #23\r
902     sub     r8, r8, #0x78   @ r8=sx\r
903 \r
904     mov     r9, lr, lsl #21\r
905     mov     r9, r9, lsr #13 @ r9=tile<<8\r
906 \r
907     and     r3, lr, #0x6000\r
908     mov     r3, r3, lsr #9  @ r3=pal=((code>>9)&0x30);\r
909 \r
910     ldr     r11, [r1, #OFS_EST_Draw2FB]\r
911     ldr     r10, [r1, #OFS_EST_PicoMem_vram]\r
912     sub     r1, r12, #(START_ROW*8)\r
913     mov     r0, #328\r
914     mla     r11, r1, r0, r11      @ scrpos+=(sy-START_ROW*8)*328;\r
915 \r
916     orr     r5, r5, r5, lsl #16   @\r
917     orr     r5, r6, r5, lsl #8    @ r5=width|(height<<8)|(height<<24)\r
918 \r
919     tst     lr, #0x1000         @ vflip?\r
920     bne     .dsf_vflip\r
921 \r
922     tst     lr, #0x0800         @ hflip?\r
923     bne     .dsf_hflip\r
924 \r
925     SpriteLoop 0, 0\r
926 \r
927 .dsf_hflip:\r
928     SpriteLoop 1, 0\r
929 \r
930 .dsf_vflip:\r
931     tst     lr, #0x0800         @ hflip?\r
932     bne     .dsf_vflip_hflip\r
933 \r
934     SpriteLoop 0, 1\r
935 \r
936 .dsf_vflip_hflip:\r
937     SpriteLoop 1, 1\r
938 \r
939 .pool\r
940 \r
941 @ vim:filetype=armasm\r