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