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