fix FS#8187 - charging breaks sleep timer. Now if the timer goes off and the player...
[Rockbox.git] / apps / plugins / rockboy / lcd.c
blobda3b138e5197dd60d96e90ebb6c8ca2e2e600f7d
1 #include "rockmacros.h"
2 #include "defs.h"
3 #include "regs.h"
4 #include "hw.h"
5 #include "mem.h"
6 #include "lcd-gb.h"
7 #include "fb.h"
8 #ifdef HAVE_LCD_COLOR
9 #include "palette-presets.h"
10 #endif
11 #ifdef USE_ASM
12 #include "asm.h"
13 #endif
15 struct lcd lcd;
17 struct scan scan IBSS_ATTR;
19 #define BG (scan.bg)
20 #define WND (scan.wnd)
22 #if LCD_DEPTH ==16
23 #define BUF (scan.buf)
24 #else
25 #define BUF (scan.buf[scanline_ind])
26 #endif
28 #define PRI (scan.pri)
30 #define PAL (scan.pal)
32 #define VS (scan.vs) /* vissprites */
33 #define NS (scan.ns)
35 #define L (scan.l) /* line */
36 #define X (scan.x) /* screen position */
37 #define Y (scan.y)
38 #define S (scan.s) /* tilemap position */
39 #define T (scan.t)
40 #define U (scan.u) /* position within tile */
41 #define V (scan.v)
42 #define WX (scan.wx)
43 #define WY (scan.wy)
44 #define WT (scan.wt)
45 #define WV (scan.wv)
47 byte patpix[4096][8][8]
48 #if defined(CPU_COLDFIRE)
49 __attribute__ ((aligned(16))) /* to profit from burst mode */
50 #endif
52 byte patdirty[1024];
53 byte anydirty;
55 #if LCD_DEPTH < 16
56 static int scanline_ind=0;
57 #endif
59 static int dmg_pal[4][4];
61 fb_data *vdest;
63 #ifndef ASM_UPDATEPATPIX
64 static void updatepatpix(void) ICODE_ATTR;
65 static void updatepatpix(void)
67 int i, j;
68 #if ((CONFIG_CPU != SH7034) && !defined(CPU_COLDFIRE))
69 int k, a, c;
70 #endif
71 byte *vram = lcd.vbank[0];
73 if (!anydirty) return;
74 for (i = 0; i < 1024; i++)
76 if (i == 384) i = 512;
77 if (i == 896) break;
78 if (!patdirty[i]) continue;
79 patdirty[i] = 0;
80 for (j = 0; j < 8; j++)
82 #if CONFIG_CPU == SH7034
83 asm volatile (
84 "mov.w @%2,r1 \n"
85 "swap.b r1,r2 \n"
87 "mov #0,r0 \n"
88 "shlr r1 \n"
89 "rotcl r0 \n"
90 "shlr r2 \n"
91 "rotcl r0 \n"
92 "mov.b r0,@%0 \n"
93 "mov.b r0,@(7,%1) \n"
94 "mov #0,r0 \n"
95 "shlr r1 \n"
96 "rotcl r0 \n"
97 "shlr r2 \n"
98 "rotcl r0 \n"
99 "mov.b r0,@(1,%0) \n"
100 "mov.b r0,@(6,%1) \n"
101 "mov #0,r0 \n"
102 "shlr r1 \n"
103 "rotcl r0 \n"
104 "shlr r2 \n"
105 "rotcl r0 \n"
106 "mov.b r0,@(2,%0) \n"
107 "mov.b r0,@(5,%1) \n"
108 "mov #0,r0 \n"
109 "shlr r1 \n"
110 "rotcl r0 \n"
111 "shlr r2 \n"
112 "rotcl r0 \n"
113 "mov.b r0,@(3,%0) \n"
114 "mov.b r0,@(4,%1) \n"
115 "mov #0,r0 \n"
116 "shlr r1 \n"
117 "rotcl r0 \n"
118 "shlr r2 \n"
119 "rotcl r0 \n"
120 "mov.b r0,@(4,%0) \n"
121 "mov.b r0,@(3,%1) \n"
122 "mov #0,r0 \n"
123 "shlr r1 \n"
124 "rotcl r0 \n"
125 "shlr r2 \n"
126 "rotcl r0 \n"
127 "mov.b r0,@(5,%0) \n"
128 "mov.b r0,@(2,%1) \n"
129 "mov #0,r0 \n"
130 "shlr r1 \n"
131 "rotcl r0 \n"
132 "shlr r2 \n"
133 "rotcl r0 \n"
134 "mov.b r0,@(6,%0) \n"
135 "mov.b r0,@(1,%1) \n"
136 "mov #0,r0 \n"
137 "shlr r1 \n"
138 "rotcl r0 \n"
139 "shlr r2 \n"
140 "rotcl r0 \n"
141 "mov.b r0,@(7,%0) \n"
142 "mov.b r0,@%1 \n"
143 : /* outputs */
144 : /* inputs */
145 /* %0 */ "r"(patpix[i+1024][j]),
146 /* %1 */ "r"(patpix[i][j]),
147 /* %2 */ "r"(&vram[(i<<4)|(j<<1)])
148 : /* clobbers */
149 "r0", "r1", "r2"
151 #elif defined(CPU_COLDFIRE)
152 asm volatile (
153 "move.b (%2),%%d2 \n"
154 "move.b (1,%2),%%d1 \n"
156 "addq.l #8,%1 \n"
157 "clr.l %%d0 \n"
158 "lsr.l #1,%%d1 \n"
159 "addx.l %%d0,%%d0 \n"
160 "lsr.l #1,%%d2 \n"
161 "addx.l %%d0,%%d0 \n"
162 "move.b %%d0,-(%1) \n"
163 "lsl.l #6,%%d0 \n"
164 "lsr.l #1,%%d1 \n"
165 "addx.l %%d0,%%d0 \n"
166 "lsr.l #1,%%d2 \n"
167 "addx.l %%d0,%%d0 \n"
168 "move.b %%d0,-(%1) \n"
169 "lsl.l #6,%%d0 \n"
170 "lsr.l #1,%%d1 \n"
171 "addx.l %%d0,%%d0 \n"
172 "lsr.l #1,%%d2 \n"
173 "addx.l %%d0,%%d0 \n"
174 "move.b %%d0,-(%1) \n"
175 "lsl.l #6,%%d0 \n"
176 "lsr.l #1,%%d1 \n"
177 "addx.l %%d0,%%d0 \n"
178 "lsr.l #1,%%d2 \n"
179 "addx.l %%d0,%%d0 \n"
180 "move.l %%d0,(%0) \n"
181 "move.b %%d0,-(%1) \n"
182 "clr.l %%d0 \n"
183 "lsr.l #1,%%d1 \n"
184 "addx.l %%d0,%%d0 \n"
185 "lsr.l #1,%%d2 \n"
186 "addx.l %%d0,%%d0 \n"
187 "move.b %%d0,-(%1) \n"
188 "lsl.l #6,%%d0 \n"
189 "lsr.l #1,%%d1 \n"
190 "addx.l %%d0,%%d0 \n"
191 "lsr.l #1,%%d2 \n"
192 "addx.l %%d0,%%d0 \n"
193 "move.b %%d0,-(%1) \n"
194 "lsl.l #6,%%d0 \n"
195 "lsr.l #1,%%d1 \n"
196 "addx.l %%d0,%%d0 \n"
197 "lsr.l #1,%%d2 \n"
198 "addx.l %%d0,%%d0 \n"
199 "move.b %%d0,-(%1) \n"
200 "lsl.l #6,%%d0 \n"
201 "lsr.l #1,%%d1 \n"
202 "addx.l %%d0,%%d0 \n"
203 "lsr.l #1,%%d2 \n"
204 "addx.l %%d0,%%d0 \n"
205 "move.l %%d0,(4,%0) \n"
206 "move.b %%d0,-(%1) \n"
207 : /* outputs */
208 : /* inputs */
209 /* %0 */ "a"(patpix[i+1024][j]),
210 /* %1 */ "a"(patpix[i][j]),
211 /* %2 */ "a"(&vram[(i<<4)|(j<<1)])
212 : /* clobbers */
213 "d0", "d1", "d2"
215 #else
216 a = ((i<<4) | (j<<1));
217 for (k = 0; k < 8; k++)
219 c = vram[a] & (1<<k) ? 1 : 0;
220 c |= vram[a+1] & (1<<k) ? 2 : 0;
221 patpix[i+1024][j][k] = c;
223 for (k = 0; k < 8; k++)
224 patpix[i][j][k] =
225 patpix[i+1024][j][7-k];
226 #endif
228 #if CONFIG_CPU == SH7034
229 asm volatile (
230 "mov.l @%0,r0 \n"
231 "mov.l @(4,%0),r1 \n"
232 "mov.l r0,@(56,%1) \n"
233 "mov.l r1,@(60,%1) \n"
234 "mov.l @(8,%0),r0 \n"
235 "mov.l @(12,%0),r1 \n"
236 "mov.l r0,@(48,%1) \n"
237 "mov.l r1,@(52,%1) \n"
238 "mov.l @(16,%0),r0 \n"
239 "mov.l @(20,%0),r1 \n"
240 "mov.l r0,@(40,%1) \n"
241 "mov.l r1,@(44,%1) \n"
242 "mov.l @(24,%0),r0 \n"
243 "mov.l @(28,%0),r1 \n"
244 "mov.l r0,@(32,%1) \n"
245 "mov.l r1,@(36,%1) \n"
246 "mov.l @(32,%0),r0 \n"
247 "mov.l @(36,%0),r1 \n"
248 "mov.l r0,@(24,%1) \n"
249 "mov.l r1,@(28,%1) \n"
250 "mov.l @(40,%0),r0 \n"
251 "mov.l @(44,%0),r1 \n"
252 "mov.l r0,@(16,%1) \n"
253 "mov.l r1,@(20,%1) \n"
254 "mov.l @(48,%0),r0 \n"
255 "mov.l @(52,%0),r1 \n"
256 "mov.l r0,@(8,%1) \n"
257 "mov.l r1,@(12,%1) \n"
258 "mov.l @(56,%0),r0 \n"
259 "mov.l @(60,%0),r1 \n"
260 "mov.l r0,@%1 \n"
261 "mov.l r1,@(4,%1) \n"
263 "add %2,%0 \n"
264 "add %2,%1 \n"
266 "mov.l @%0,r0 \n"
267 "mov.l @(4,%0),r1 \n"
268 "mov.l r0,@(56,%1) \n"
269 "mov.l r1,@(60,%1) \n"
270 "mov.l @(8,%0),r0 \n"
271 "mov.l @(12,%0),r1 \n"
272 "mov.l r0,@(48,%1) \n"
273 "mov.l r1,@(52,%1) \n"
274 "mov.l @(16,%0),r0 \n"
275 "mov.l @(20,%0),r1 \n"
276 "mov.l r0,@(40,%1) \n"
277 "mov.l r1,@(44,%1) \n"
278 "mov.l @(24,%0),r0 \n"
279 "mov.l @(28,%0),r1 \n"
280 "mov.l r0,@(32,%1) \n"
281 "mov.l r1,@(36,%1) \n"
282 "mov.l @(32,%0),r0 \n"
283 "mov.l @(36,%0),r1 \n"
284 "mov.l r0,@(24,%1) \n"
285 "mov.l r1,@(28,%1) \n"
286 "mov.l @(40,%0),r0 \n"
287 "mov.l @(44,%0),r1 \n"
288 "mov.l r0,@(16,%1) \n"
289 "mov.l r1,@(20,%1) \n"
290 "mov.l @(48,%0),r0 \n"
291 "mov.l @(52,%0),r1 \n"
292 "mov.l r0,@(8,%1) \n"
293 "mov.l r1,@(12,%1) \n"
294 "mov.l @(56,%0),r0 \n"
295 "mov.l @(60,%0),r1 \n"
296 "mov.l r0,@%1 \n"
297 "mov.l r1,@(4,%1) \n"
298 : /* outputs */
299 : /* inputs */
300 /* %0 */ "r"(patpix[i][0]),
301 /* %1 */ "r"(patpix[i+2048][0]),
302 /* %2 */ "r"(1024*64)
303 : /* clobbers */
304 "r0", "r1"
306 #elif defined(CPU_COLDFIRE)
307 asm volatile (
308 "movem.l (%0),%%d0-%%d3 \n"
309 "move.l %%d0,%%d4 \n"
310 "move.l %%d1,%%d5 \n"
311 "movem.l %%d2-%%d5,(48,%1) \n"
312 "movem.l (16,%0),%%d0-%%d3 \n"
313 "move.l %%d0,%%d4 \n"
314 "move.l %%d1,%%d5 \n"
315 "movem.l %%d2-%%d5,(32,%1) \n"
316 "movem.l (32,%0),%%d0-%%d3 \n"
317 "move.l %%d0,%%d4 \n"
318 "move.l %%d1,%%d5 \n"
319 "movem.l %%d2-%%d5,(16,%1) \n"
320 "movem.l (48,%0),%%d0-%%d3 \n"
321 "move.l %%d0,%%d4 \n"
322 "move.l %%d1,%%d5 \n"
323 "movem.l %%d2-%%d5,(%1) \n"
325 "move.l %2,%%d0 \n"
326 "add.l %%d0,%0 \n"
327 "add.l %%d0,%1 \n"
329 "movem.l (%0),%%d0-%%d3 \n"
330 "move.l %%d0,%%d4 \n"
331 "move.l %%d1,%%d5 \n"
332 "movem.l %%d2-%%d5,(48,%1) \n"
333 "movem.l (16,%0),%%d0-%%d3 \n"
334 "move.l %%d0,%%d4 \n"
335 "move.l %%d1,%%d5 \n"
336 "movem.l %%d2-%%d5,(32,%1) \n"
337 "movem.l (32,%0),%%d0-%%d3 \n"
338 "move.l %%d0,%%d4 \n"
339 "move.l %%d1,%%d5 \n"
340 "movem.l %%d2-%%d5,(16,%1) \n"
341 "movem.l (48,%0),%%d0-%%d3 \n"
342 "move.l %%d0,%%d4 \n"
343 "move.l %%d1,%%d5 \n"
344 "movem.l %%d2-%%d5,(%1) \n"
345 : /* outputs */
346 : /* inputs */
347 /* %0 */ "a"(patpix[i][0]),
348 /* %1 */ "a"(patpix[i+2048][0]),
349 /* %2 */ "i"(1024*64)
350 : /* clobbers */
351 "d0", "d1", "d2", "d3", "d4", "d5"
353 #else
354 for (j = 0; j < 8; j++)
356 for (k = 0; k < 8; k++)
358 patpix[i+2048][j][k] =
359 patpix[i][7-j][k];
360 patpix[i+3072][j][k] =
361 patpix[i+1024][7-j][k];
364 #endif
366 anydirty = 0;
368 #endif /* ASM_UPDATEPATPIX */
372 static void tilebuf(void) ICODE_ATTR;
373 static void tilebuf(void)
375 int i, cnt;
376 int base;
377 byte *tilemap, *attrmap;
378 int *tilebuf;
379 int *wrap;
380 static int wraptable[64] =
382 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
383 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,-32
386 base = ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5) + S;
387 tilemap = lcd.vbank[0] + base;
388 attrmap = lcd.vbank[1] + base;
389 tilebuf = BG;
390 wrap = wraptable + S;
391 cnt = ((WX + 7) >> 3) + 1;
393 if (hw.cgb) {
394 if (R_LCDC & 0x10)
395 for (i = cnt; i > 0; i--)
397 *(tilebuf++) = *tilemap
398 | (((int)*attrmap & 0x08) << 6)
399 | (((int)*attrmap & 0x60) << 5);
400 *(tilebuf++) = (((int)*attrmap & 0x07) << 2);
401 attrmap += *wrap + 1;
402 tilemap += *(wrap++) + 1;
404 else
405 for (i = cnt; i > 0; i--)
407 *(tilebuf++) = (256 + ((n8)*tilemap))
408 | (((int)*attrmap & 0x08) << 6)
409 | (((int)*attrmap & 0x60) << 5);
410 *(tilebuf++) = (((int)*attrmap & 0x07) << 2);
411 attrmap += *wrap + 1;
412 tilemap += *(wrap++) + 1;
415 else
417 if (R_LCDC & 0x10)
418 for (i = cnt; i > 0; i--)
420 *(tilebuf++) = *(tilemap++);
421 tilemap += *(wrap++);
423 else
424 for (i = cnt; i > 0; i--)
426 *(tilebuf++) = (256 + ((n8)*(tilemap++)));
427 tilemap += *(wrap++);
431 if (WX >= 160) return;
433 base = ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5);
434 tilemap = lcd.vbank[0] + base;
435 attrmap = lcd.vbank[1] + base;
436 tilebuf = WND;
437 cnt = ((160 - WX) >> 3) + 1;
439 if (hw.cgb)
441 if (R_LCDC & 0x10)
442 for (i = cnt; i > 0; i--)
444 *(tilebuf++) = *(tilemap++)
445 | (((int)*attrmap & 0x08) << 6)
446 | (((int)*attrmap & 0x60) << 5);
447 *(tilebuf++) = (((int)*(attrmap++)&7) << 2);
449 else
450 for (i = cnt; i > 0; i--)
452 *(tilebuf++) = (256 + ((n8)*(tilemap++)))
453 | (((int)*attrmap & 0x08) << 6)
454 | (((int)*attrmap & 0x60) << 5);
455 *(tilebuf++) = (((int)*(attrmap++)&7) << 2);
458 else
461 if (R_LCDC & 0x10)
462 for (i = cnt; i > 0; i--)
463 *(tilebuf++) = *(tilemap++);
464 else
465 for (i = cnt; i > 0; i--)
466 *(tilebuf++) = (256 + ((n8)*(tilemap++)));
471 /* V = vertical line
472 * WX = WND start (if 0, no need to do anything) -> WY
473 * U = start...something...thingy... 7 at most
475 static void bg_scan(void) ICODE_ATTR;
476 static void bg_scan(void)
478 int cnt;
479 byte *src, *dest;
480 int *tile;
482 if (WX <= 0) return;
483 cnt = WX;
484 tile = BG;
485 dest = BUF;
487 src = patpix[*(tile++)][V] + U;
488 memcpy(dest, src, 8-U);
489 dest += 8-U;
490 cnt -= 8-U;
491 if (cnt <= 0) return;
492 while (cnt >= 8)
494 #if defined(CPU_COLDFIRE)
495 asm volatile (
496 "move.l (%1)+,(%0)+ \n"
497 "move.l (%1)+,(%0)+ \n"
498 : /*outputs*/
499 : /*inputs*/
500 /* %0 */ "a" (dest),
501 /* %1 */ "a" (patpix[*(tile++)][V])
502 //: /* clobbers */
504 #else
505 src = patpix[*(tile++)][V];
506 memcpy(dest,src,8);
507 dest += 8;
508 #endif
509 cnt -= 8;
511 src = patpix[*tile][V];
512 while (cnt--)
513 *(dest++) = *(src++);
516 static void wnd_scan(void) ICODE_ATTR;
517 static void wnd_scan(void)
519 int cnt;
520 byte *src, *dest;
521 int *tile;
523 if (WX >= 160) return;
524 cnt = 160 - WX;
525 tile = WND;
526 dest = BUF + WX;
528 while (cnt >= 8)
530 #if defined(CPU_COLDFIRE)
531 asm volatile (
532 "move.l (%1)+,(%0)+ \n"
533 "move.l (%1)+,(%0)+ \n"
534 : /*outputs*/
535 : /*inputs*/
536 /* %0 */ "a" (dest),
537 /* %1 */ "a" (patpix[*(tile++)][WV])
538 //: /* clobbers */
540 #else
541 src = patpix[*(tile++)][WV];
542 memcpy(dest,src,8);
543 dest += 8;
544 #endif
545 cnt -= 8;
547 src = patpix[*tile][WV];
548 while (cnt--)
549 *(dest++) = *(src++);
552 static void blendcpy(byte *dest, byte *src, byte b, int cnt)
554 while (cnt--) *(dest++) = *(src++) | b;
557 static int priused(void *attr)
559 un32 *a = attr;
560 return (int)((a[0]|a[1]|a[2]|a[3]|a[4]|a[5]|a[6]|a[7])&0x80808080);
563 static void bg_scan_pri(void) ICODE_ATTR;
564 static void bg_scan_pri(void)
566 int cnt, i;
567 byte *src, *dest;
569 if (WX <= 0) return;
570 i = S;
571 cnt = WX;
572 dest = PRI;
573 src = lcd.vbank[1] + ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5);
575 if (!priused(src))
577 memset(dest, 0, cnt);
578 return;
581 memset(dest, src[i++&31]&128, 8-U);
582 dest += 8-U;
583 cnt -= 8-U;
584 if (cnt <= 0) return;
585 while (cnt >= 8)
587 memset(dest, src[i++&31]&128, 8);
588 dest += 8;
589 cnt -= 8;
591 memset(dest, src[i&31]&128, cnt);
594 static void wnd_scan_pri(void) ICODE_ATTR;
595 static void wnd_scan_pri(void)
597 int cnt, i;
598 byte *src, *dest;
600 if (WX >= 160) return;
601 i = 0;
602 cnt = 160 - WX;
603 dest = PRI + WX;
604 src = lcd.vbank[1] + ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5);
606 if (!priused(src))
608 memset(dest, 0, cnt);
609 return;
612 while (cnt >= 8)
614 memset(dest, src[i++]&128, 8);
615 dest += 8;
616 cnt -= 8;
618 memset(dest, src[i]&128, cnt);
621 static void bg_scan_color(void)
623 int cnt;
624 byte *src, *dest;
625 int *tile;
627 if (WX <= 0) return;
628 cnt = WX;
629 tile = BG;
630 dest = BUF;
632 src = patpix[*(tile++)][V] + U;
633 blendcpy(dest, src, *(tile++), 8-U);
634 dest += 8-U;
635 cnt -= 8-U;
636 if (cnt <= 0) return;
637 while (cnt >= 8)
639 src = patpix[*(tile++)][V];
640 #if defined(CPU_COLDFIRE)
641 asm volatile (
642 "move.l (%2)+,%%d1 \n"
644 "move.b %%d1,%%d2 \n"
646 "move.b (%1)+,%%d0 \n"
647 "or.l %%d2,%%d0 \n"
648 "move.b %%d0,(%0)+ \n"
650 "move.b (%1)+,%%d0 \n"
651 "or.l %%d1,%%d0 \n"
652 "move.b %%d0,(%0)+ \n"
654 "move.b (%1)+,%%d0 \n"
655 "or.l %%d2,%%d0 \n"
656 "move.b %%d0,(%0)+ \n"
658 "move.b (%1)+,%%d0 \n"
659 "or.l %%d2,%%d0 \n"
660 "move.b %%d0,(%0)+ \n"
662 "move.b (%1)+,%%d0 \n"
663 "or.l %%d2,%%d0 \n"
664 "move.b %%d0,(%0)+ \n"
666 "move.b (%1)+,%%d0 \n"
667 "or.l %%d2,%%d0 \n"
668 "move.b %%d0,(%0)+ \n"
670 "move.b (%1)+,%%d0 \n"
671 "or.l %%d2,%%d0 \n"
672 "move.b %%d0,(%0)+ \n"
674 "move.b (%1)+,%%d0 \n"
675 "or.l %%d2,%%d0 \n"
676 "move.b %%d0,(%0)+ \n"
677 : /*outputs*/
678 : /*inputs*/
679 /* %0 */ "a" (dest),
680 /* %1 */ "a" (src),
681 /* %2 */ "a" (tile)
682 : /* clobbers */
683 "d0", "d1", "d2"
685 #else
686 blendcpy(dest, src, *(tile++), 8);
687 dest += 8;
688 #endif
689 cnt -= 8;
691 src = patpix[*(tile++)][V];
692 blendcpy(dest, src, *(tile++), cnt);
695 static void wnd_scan_color(void)
697 int cnt;
698 byte *src, *dest;
699 int *tile;
701 if (WX >= 160) return;
702 cnt = 160 - WX;
703 tile = WND;
704 dest = BUF + WX;
706 while (cnt >= 8)
708 src = patpix[*(tile++)][WV];
709 blendcpy(dest, src, *(tile++), 8);
710 dest += 8;
711 cnt -= 8;
713 src = patpix[*(tile++)][WV];
714 blendcpy(dest, src, *(tile++), cnt);
717 static void spr_enum(void) ICODE_ATTR;
718 static void spr_enum(void)
720 int i, j;
721 struct obj *o;
722 struct vissprite ts;
723 int v, pat;
725 NS = 0;
726 if (!(R_LCDC & 0x02)) return;
728 o = lcd.oam.obj;
730 for (i = 40; i; i--, o++)
732 if (L >= o->y || L + 16 < o->y)
733 continue;
734 if (L + 8 >= o->y && !(R_LCDC & 0x04))
735 continue;
736 VS[NS].x = (int)o->x - 8;
737 v = L - (int)o->y + 16;
738 if (hw.cgb)
740 pat = o->pat | (((int)o->flags & 0x60) << 5)
741 | (((int)o->flags & 0x08) << 6);
742 VS[NS].pal = 32 + ((o->flags & 0x07) << 2);
744 else
746 pat = o->pat | (((int)o->flags & 0x60) << 5);
747 VS[NS].pal = 32 + ((o->flags & 0x10) >> 2);
749 VS[NS].pri = (o->flags & 0x80) >> 7;
750 if ((R_LCDC & 0x04))
752 pat &= ~1;
753 if (v >= 8)
755 v -= 8;
756 pat++;
758 if (o->flags & 0x40) pat ^= 1;
760 VS[NS].buf = patpix[pat][v];
761 if (++NS == 10) break;
763 if (hw.cgb) return;
764 for (i = 0; i < NS; i++)
766 for (j = i + 1; j < NS; j++)
768 if (VS[i].x > VS[j].x)
770 ts = VS[i];
771 VS[i] = VS[j];
772 VS[j] = ts;
778 static void spr_scan(void) ICODE_ATTR;
779 static void spr_scan(void)
781 int i, x;
782 byte pal, b, ns = NS;
783 byte *src, *dest, *bg, *pri;
784 struct vissprite *vs;
785 static byte bgdup[256];
787 if (!ns) return;
789 memcpy(bgdup, BUF, 256);
790 vs = &VS[ns-1];
792 for (; ns; ns--, vs--)
794 x = vs->x;
795 if (x > 159) continue;
796 if (x < -7) continue;
797 if (x < 0)
799 src = vs->buf - x;
800 dest = BUF;
801 i = 8 + x;
803 else
805 src = vs->buf;
806 dest = BUF + x;
807 if (x > 152) i = 160 - x;
808 else i = 8;
810 pal = vs->pal;
811 if (vs->pri)
813 bg = bgdup + (dest - BUF);
814 while (i--)
816 b = src[i];
817 if (b && !(bg[i]&3)) dest[i] = pal|b;
820 else if (hw.cgb)
822 bg = bgdup + (dest - BUF);
823 pri = PRI + (dest - BUF);
824 while (i--)
826 b = src[i];
827 if (b && (!pri[i] || !(bg[i]&3)))
828 dest[i] = pal|b;
831 else while (i--) if (src[i]) dest[i] = pal|src[i];
835 /* Scaling defines */
836 #define DX ((LCD_WIDTH<<16) / 160)
837 #define DXI ((160<<16) / LCD_WIDTH)
838 #define DY ((LCD_HEIGHT<<16) / 144)
839 #define DYI ((144<<16) / LCD_HEIGHT)
841 #define DXR ((LCD_WIDTH<<16) / 144)
842 #define DXIR ((144<<16) / LCD_WIDTH)
843 #define DYR ((LCD_HEIGHT<<16) / 160)
844 #define DYIR ((160<<16) / LCD_HEIGHT)
846 void lcd_begin(void)
849 #if (LCD_WIDTH>=160) && (LCD_HEIGHT>=144)
850 #define S1 ((LCD_HEIGHT-144)/2)*LCD_WIDTH + ((LCD_WIDTH-160)/2)
851 #define S2 0
852 #define S1R ((LCD_HEIGHT-160)/2)*LCD_WIDTH + ((LCD_WIDTH-144)/2)+144
853 #define S2R (LCD_WIDTH-1)
855 #elif (LCD_WIDTH>=160) && (LCD_HEIGHT<=144)
856 #define S1 0
857 #define S2 0
858 #define S1R LCD_WIDTH-1
859 #define S2R LCD_WIDTH-1
861 #elif (LCD_WIDTH<=160) && (LCD_HEIGHT>=144)
862 #define S1 ((LCD_HEIGHT-144)/2)*LCD_WIDTH
863 #define S2 ((LCD_HEIGHT-144)/2)*LCD_WIDTH
864 #define S1R LCD_WIDTH-1
865 #define S2R LCD_WIDTH-1
867 #else
868 #define S1 0
869 #define S2 0
870 #define S1R LCD_WIDTH-1
871 #define S2R LCD_WIDTH-1
872 #endif
874 #if (LCD_WIDTH>LCD_HEIGHT)
875 #define S3 ((LCD_WIDTH-((160*DY)>>16))/2)
876 #define S3R LCD_WIDTH-1
877 #else
878 #define S3 ((LCD_HEIGHT-((144*DX)>>16))/2)*LCD_WIDTH
879 #define S3R ((LCD_HEIGHT-((160*DXR)>>16))/2)*LCD_WIDTH+LCD_WIDTH-1
880 #endif
882 vdest=rb->lcd_framebuffer;
883 #ifdef HAVE_LCD_COLOR
884 set_pal();
886 if(options.rotate)
888 if(options.scaling == 0)
889 vdest+=+S2R;
890 else if (options.scaling == 1)
891 vdest+=S3R;
892 else
893 vdest+=S1R;
895 else
897 if(options.scaling == 0)
898 vdest+=S2;
899 else if (options.scaling == 1)
900 vdest+=S3;
901 else
902 vdest+=S1;
904 #endif
905 WY = R_WY;
908 #ifdef HAVE_LCD_COLOR
909 int SCALEWL IDATA_ATTR=1<<16;
910 int SCALEWS IDATA_ATTR=1<<16;
911 int SCALEHL IDATA_ATTR=1<<16;
912 int SCALEHS IDATA_ATTR=1<<16;
913 int swidth IDATA_ATTR=160;
914 int sremain IDATA_ATTR=LCD_WIDTH-160;
915 #endif
917 void setvidmode(void)
919 #ifdef HAVE_LCD_COLOR
920 switch(options.scaling)
922 case 0:
923 if(options.rotate)
925 SCALEWL=DYR;
926 SCALEWS=DYIR;
927 SCALEHL=DXR;
928 SCALEHS=DXIR;
930 else
932 SCALEWL=DX;
933 SCALEWS=DXI;
934 SCALEHL=DY;
935 SCALEHS=DYI;
937 break;
938 case 1: /* Maintain Ratio */
939 if(options.rotate)
941 if (DYR<DXR)
943 SCALEWL=DYR;
944 SCALEWS=DYIR;
945 SCALEHL=DYR;
946 SCALEHS=DYIR;
948 else
950 SCALEWL=DXR;
951 SCALEWS=DXIR;
952 SCALEHL=DXR;
953 SCALEHS=DXIR;
956 else
958 if (DY<DX)
960 SCALEWL=DY;
961 SCALEWS=DYI;
962 SCALEHL=DY;
963 SCALEHS=DYI;
965 else
967 SCALEWL=DX;
968 SCALEWS=DXI;
969 SCALEHL=DX;
970 SCALEHS=DXI;
973 break;
974 default:
975 SCALEWL=1<<16;
976 SCALEWS=1<<16;
977 SCALEHL=1<<16;
978 SCALEHS=1<<16;
980 swidth=(160*SCALEWL)>>16;
982 if(options.rotate)
983 sremain=-(((160*SCALEWL)>>16)*LCD_WIDTH+1);
984 else
985 sremain=LCD_WIDTH-swidth;
986 #endif
989 void lcd_refreshline(void)
991 #ifdef HAVE_LCD_COLOR
992 char frameout[30];
993 #endif
995 if (!(R_LCDC & 0x80))
996 return; /* should not happen... */
998 #if (LCD_HEIGHT <= 128) && !defined(HAVE_LCD_COLOR)
999 if ( (fb.mode==0&&(R_LY >= 128)) ||
1000 (fb.mode==1&&(R_LY < 16)) ||
1001 (fb.mode==2&&(R_LY<8||R_LY>=136)) ||
1002 (fb.mode==3&&((R_LY%9)==8))
1004 #if LCD_HEIGHT == 64
1005 || (R_LY & 1) /* calculate only even lines */
1006 #endif
1008 return;
1009 #endif
1011 updatepatpix();
1013 L = R_LY;
1014 X = R_SCX;
1015 Y = (R_SCY + L) & 0xff;
1016 S = X >> 3;
1017 T = Y >> 3;
1018 U = X & 7;
1019 V = Y & 7;
1021 WX = R_WX - 7;
1022 if (WY>L || WY<0 || WY>143 || WX<-7 || WX>159 || !(R_LCDC&0x20))
1023 WX = 160;
1024 WT = (L - WY) >> 3;
1025 WV = (L - WY) & 7;
1027 spr_enum();
1029 tilebuf();
1030 if (hw.cgb)
1032 bg_scan_color();
1033 wnd_scan_color();
1034 if (NS)
1036 bg_scan_pri();
1037 wnd_scan_pri();
1040 else
1043 bg_scan();
1044 wnd_scan();
1046 spr_scan();
1048 #if !defined(HAVE_LCD_COLOR)
1049 #if LCD_DEPTH == 1
1050 if (scanline_ind == 7)
1051 #elif LCD_DEPTH == 2
1052 if (scanline_ind == 3)
1053 #endif
1055 if(fb.mode!=3)
1056 vid_update(L);
1057 else
1058 vid_update(L-((int)(L/9)));
1059 #else
1061 /* Universal Scaling pulled from PrBoom and modified for rockboy */
1063 static int hpt IDATA_ATTR=0x8000;
1065 while((hpt>>16)<L+1)
1067 hpt+=SCALEHS;
1068 register unsigned int srcpt=0x8000;
1069 register unsigned int wcount=swidth;
1070 register unsigned int remain=sremain;
1071 while(wcount--)
1073 *vdest = PAL[BUF[srcpt>>16]];
1074 if (options.rotate)
1075 vdest+=LCD_WIDTH;
1076 else
1077 vdest++;
1079 srcpt+=SCALEWS;
1081 vdest+=remain;
1084 if(L==143)
1086 if(options.showstats)
1088 snprintf(frameout,sizeof(frameout),"FPS: %d Frameskip: %d ",options.fps, options.frameskip);
1089 rb->lcd_putsxy(0,LCD_HEIGHT-10,frameout);
1092 hpt=0x8000;
1093 rb->lcd_update();
1096 #endif
1098 #if LCD_DEPTH == 1
1099 scanline_ind = (scanline_ind+1) % 8;
1100 #elif LCD_DEPTH == 2
1101 scanline_ind = (scanline_ind+1) % 4;
1102 #endif
1105 #ifdef HAVE_LCD_COLOR
1106 void set_pal(void)
1108 memcpy(dmg_pal,palettes[options.pal], sizeof(dmg_pal));
1109 pal_dirty();
1112 static void updatepalette(int i)
1114 int c, r, g, b;
1116 c = (lcd.pal[i<<1] | ((int)lcd.pal[(i<<1)|1] << 8)) & 0x7FFF;
1117 r = (c & 0x001F) << 3;
1118 g = (c & 0x03E0) >> 2;
1119 b = (c & 0x7C00) >> 7;
1120 r |= (r >> 5);
1121 g |= (g >> 5);
1122 b |= (b >> 5);
1124 r = (r >> fb.cc[0].r) << fb.cc[0].l;
1125 g = (g >> fb.cc[1].r) << fb.cc[1].l;
1126 b = (b >> fb.cc[2].r) << fb.cc[2].l;
1128 #if LCD_PIXELFORMAT == RGB565
1129 c = r|g|b;
1130 #elif LCD_PIXELFORMAT == RGB565SWAPPED
1131 c = swap16(r|g|b);
1132 #endif
1133 PAL[i] = c;
1135 #endif /* HAVE_LCD_COLOR */
1137 void pal_write(int i, byte b)
1139 if (lcd.pal[i] == b) return;
1140 lcd.pal[i] = b;
1141 #ifdef HAVE_LCD_COLOR
1142 updatepalette(i>>1);
1143 #endif
1146 void pal_write_dmg(int i, int mapnum, byte d)
1148 int j;
1149 int *cmap = dmg_pal[mapnum];
1150 int c, r, g, b;
1152 if (hw.cgb) return;
1154 for (j = 0; j < 8; j += 2)
1156 c = cmap[(d >> j) & 3];
1157 r = (c & 0xf8) >> 3;
1158 g = (c & 0xf800) >> 6;
1159 b = (c & 0xf80000) >> 9;
1160 c = r|g|b;
1161 /* FIXME - handle directly without faking cgb */
1162 pal_write(i+j, c & 0xff);
1163 pal_write(i+j+1, c >> 8);
1167 void vram_write(addr a, byte b)
1169 lcd.vbank[R_VBK&1][a] = b;
1170 if (a >= 0x1800) return;
1171 patdirty[((R_VBK&1)<<9)+(a>>4)] = 1;
1172 anydirty = 1;
1175 void vram_dirty(void)
1177 anydirty = 1;
1178 memset(patdirty, 1, sizeof patdirty);
1181 void pal_dirty(void)
1183 #ifdef HAVE_LCD_COLOR
1184 int i;
1185 #endif
1186 if (!hw.cgb)
1189 pal_write_dmg(0, 0, R_BGP);
1190 pal_write_dmg(8, 1, R_BGP);
1191 pal_write_dmg(64, 2, R_OBP0);
1192 pal_write_dmg(72, 3, R_OBP1);
1194 #ifdef HAVE_LCD_COLOR
1195 for (i = 0; i < 64; i++)
1196 updatepalette(i);
1197 #endif
1200 void lcd_reset(void)
1202 memset(&lcd, 0, sizeof lcd);
1203 lcd_begin();
1204 vram_dirty();