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