FS#12076 - DB stats resurrection: If the filename was changed, require
[kugel-rb.git] / apps / plugins / rockboy / lcd.c
blob2dc983f812e33db5261ea55f8d92deda9d22c572
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 #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
62 unsigned char *vdest;
63 #else
64 fb_data *vdest;
65 #endif
67 #ifndef ASM_UPDATEPATPIX
68 static void updatepatpix(void) ICODE_ATTR;
69 static void updatepatpix(void)
71 int i, j;
72 #if ((CONFIG_CPU != SH7034) && !defined(CPU_COLDFIRE))
73 int k, a, c;
74 #endif
75 byte *vram = lcd.vbank[0];
77 if (!anydirty) return;
78 for (i = 0; i < 1024; i++)
80 if (i == 384) i = 512;
81 if (i == 896) break;
82 if (!patdirty[i]) continue;
83 patdirty[i] = 0;
84 for (j = 0; j < 8; j++)
86 #if CONFIG_CPU == SH7034
87 asm volatile (
88 "mov.w @%2,r1 \n"
89 "swap.b r1,r2 \n"
91 "mov #0,r0 \n"
92 "shlr r1 \n"
93 "rotcl r0 \n"
94 "shlr r2 \n"
95 "rotcl r0 \n"
96 "mov.b r0,@%0 \n"
97 "mov.b r0,@(7,%1) \n"
98 "mov #0,r0 \n"
99 "shlr r1 \n"
100 "rotcl r0 \n"
101 "shlr r2 \n"
102 "rotcl r0 \n"
103 "mov.b r0,@(1,%0) \n"
104 "mov.b r0,@(6,%1) \n"
105 "mov #0,r0 \n"
106 "shlr r1 \n"
107 "rotcl r0 \n"
108 "shlr r2 \n"
109 "rotcl r0 \n"
110 "mov.b r0,@(2,%0) \n"
111 "mov.b r0,@(5,%1) \n"
112 "mov #0,r0 \n"
113 "shlr r1 \n"
114 "rotcl r0 \n"
115 "shlr r2 \n"
116 "rotcl r0 \n"
117 "mov.b r0,@(3,%0) \n"
118 "mov.b r0,@(4,%1) \n"
119 "mov #0,r0 \n"
120 "shlr r1 \n"
121 "rotcl r0 \n"
122 "shlr r2 \n"
123 "rotcl r0 \n"
124 "mov.b r0,@(4,%0) \n"
125 "mov.b r0,@(3,%1) \n"
126 "mov #0,r0 \n"
127 "shlr r1 \n"
128 "rotcl r0 \n"
129 "shlr r2 \n"
130 "rotcl r0 \n"
131 "mov.b r0,@(5,%0) \n"
132 "mov.b r0,@(2,%1) \n"
133 "mov #0,r0 \n"
134 "shlr r1 \n"
135 "rotcl r0 \n"
136 "shlr r2 \n"
137 "rotcl r0 \n"
138 "mov.b r0,@(6,%0) \n"
139 "mov.b r0,@(1,%1) \n"
140 "mov #0,r0 \n"
141 "shlr r1 \n"
142 "rotcl r0 \n"
143 "shlr r2 \n"
144 "rotcl r0 \n"
145 "mov.b r0,@(7,%0) \n"
146 "mov.b r0,@%1 \n"
147 : /* outputs */
148 : /* inputs */
149 /* %0 */ "r"(patpix[i+1024][j]),
150 /* %1 */ "r"(patpix[i][j]),
151 /* %2 */ "r"(&vram[(i<<4)|(j<<1)])
152 : /* clobbers */
153 "r0", "r1", "r2"
155 #elif defined(CPU_COLDFIRE)
156 asm volatile (
157 "move.b (%2),%%d2 \n"
158 "move.b (1,%2),%%d1 \n"
160 "addq.l #8,%1 \n"
161 "clr.l %%d0 \n"
162 "lsr.l #1,%%d1 \n"
163 "addx.l %%d0,%%d0 \n"
164 "lsr.l #1,%%d2 \n"
165 "addx.l %%d0,%%d0 \n"
166 "move.b %%d0,-(%1) \n"
167 "lsl.l #6,%%d0 \n"
168 "lsr.l #1,%%d1 \n"
169 "addx.l %%d0,%%d0 \n"
170 "lsr.l #1,%%d2 \n"
171 "addx.l %%d0,%%d0 \n"
172 "move.b %%d0,-(%1) \n"
173 "lsl.l #6,%%d0 \n"
174 "lsr.l #1,%%d1 \n"
175 "addx.l %%d0,%%d0 \n"
176 "lsr.l #1,%%d2 \n"
177 "addx.l %%d0,%%d0 \n"
178 "move.b %%d0,-(%1) \n"
179 "lsl.l #6,%%d0 \n"
180 "lsr.l #1,%%d1 \n"
181 "addx.l %%d0,%%d0 \n"
182 "lsr.l #1,%%d2 \n"
183 "addx.l %%d0,%%d0 \n"
184 "move.l %%d0,(%0) \n"
185 "move.b %%d0,-(%1) \n"
186 "clr.l %%d0 \n"
187 "lsr.l #1,%%d1 \n"
188 "addx.l %%d0,%%d0 \n"
189 "lsr.l #1,%%d2 \n"
190 "addx.l %%d0,%%d0 \n"
191 "move.b %%d0,-(%1) \n"
192 "lsl.l #6,%%d0 \n"
193 "lsr.l #1,%%d1 \n"
194 "addx.l %%d0,%%d0 \n"
195 "lsr.l #1,%%d2 \n"
196 "addx.l %%d0,%%d0 \n"
197 "move.b %%d0,-(%1) \n"
198 "lsl.l #6,%%d0 \n"
199 "lsr.l #1,%%d1 \n"
200 "addx.l %%d0,%%d0 \n"
201 "lsr.l #1,%%d2 \n"
202 "addx.l %%d0,%%d0 \n"
203 "move.b %%d0,-(%1) \n"
204 "lsl.l #6,%%d0 \n"
205 "lsr.l #1,%%d1 \n"
206 "addx.l %%d0,%%d0 \n"
207 "lsr.l #1,%%d2 \n"
208 "addx.l %%d0,%%d0 \n"
209 "move.l %%d0,(4,%0) \n"
210 "move.b %%d0,-(%1) \n"
211 : /* outputs */
212 : /* inputs */
213 /* %0 */ "a"(patpix[i+1024][j]),
214 /* %1 */ "a"(patpix[i][j]),
215 /* %2 */ "a"(&vram[(i<<4)|(j<<1)])
216 : /* clobbers */
217 "d0", "d1", "d2"
219 #else
220 a = ((i<<4) | (j<<1));
221 for (k = 0; k < 8; k++)
223 c = vram[a] & BIT_N(k) ? 1 : 0;
224 c |= vram[a+1] & BIT_N(k) ? 2 : 0;
225 patpix[i+1024][j][k] = c;
227 for (k = 0; k < 8; k++)
228 patpix[i][j][k] =
229 patpix[i+1024][j][7-k];
230 #endif
232 #if CONFIG_CPU == SH7034
233 asm volatile (
234 "mov.l @%0,r0 \n"
235 "mov.l @(4,%0),r1 \n"
236 "mov.l r0,@(56,%1) \n"
237 "mov.l r1,@(60,%1) \n"
238 "mov.l @(8,%0),r0 \n"
239 "mov.l @(12,%0),r1 \n"
240 "mov.l r0,@(48,%1) \n"
241 "mov.l r1,@(52,%1) \n"
242 "mov.l @(16,%0),r0 \n"
243 "mov.l @(20,%0),r1 \n"
244 "mov.l r0,@(40,%1) \n"
245 "mov.l r1,@(44,%1) \n"
246 "mov.l @(24,%0),r0 \n"
247 "mov.l @(28,%0),r1 \n"
248 "mov.l r0,@(32,%1) \n"
249 "mov.l r1,@(36,%1) \n"
250 "mov.l @(32,%0),r0 \n"
251 "mov.l @(36,%0),r1 \n"
252 "mov.l r0,@(24,%1) \n"
253 "mov.l r1,@(28,%1) \n"
254 "mov.l @(40,%0),r0 \n"
255 "mov.l @(44,%0),r1 \n"
256 "mov.l r0,@(16,%1) \n"
257 "mov.l r1,@(20,%1) \n"
258 "mov.l @(48,%0),r0 \n"
259 "mov.l @(52,%0),r1 \n"
260 "mov.l r0,@(8,%1) \n"
261 "mov.l r1,@(12,%1) \n"
262 "mov.l @(56,%0),r0 \n"
263 "mov.l @(60,%0),r1 \n"
264 "mov.l r0,@%1 \n"
265 "mov.l r1,@(4,%1) \n"
267 "add %2,%0 \n"
268 "add %2,%1 \n"
270 "mov.l @%0,r0 \n"
271 "mov.l @(4,%0),r1 \n"
272 "mov.l r0,@(56,%1) \n"
273 "mov.l r1,@(60,%1) \n"
274 "mov.l @(8,%0),r0 \n"
275 "mov.l @(12,%0),r1 \n"
276 "mov.l r0,@(48,%1) \n"
277 "mov.l r1,@(52,%1) \n"
278 "mov.l @(16,%0),r0 \n"
279 "mov.l @(20,%0),r1 \n"
280 "mov.l r0,@(40,%1) \n"
281 "mov.l r1,@(44,%1) \n"
282 "mov.l @(24,%0),r0 \n"
283 "mov.l @(28,%0),r1 \n"
284 "mov.l r0,@(32,%1) \n"
285 "mov.l r1,@(36,%1) \n"
286 "mov.l @(32,%0),r0 \n"
287 "mov.l @(36,%0),r1 \n"
288 "mov.l r0,@(24,%1) \n"
289 "mov.l r1,@(28,%1) \n"
290 "mov.l @(40,%0),r0 \n"
291 "mov.l @(44,%0),r1 \n"
292 "mov.l r0,@(16,%1) \n"
293 "mov.l r1,@(20,%1) \n"
294 "mov.l @(48,%0),r0 \n"
295 "mov.l @(52,%0),r1 \n"
296 "mov.l r0,@(8,%1) \n"
297 "mov.l r1,@(12,%1) \n"
298 "mov.l @(56,%0),r0 \n"
299 "mov.l @(60,%0),r1 \n"
300 "mov.l r0,@%1 \n"
301 "mov.l r1,@(4,%1) \n"
302 : /* outputs */
303 : /* inputs */
304 /* %0 */ "r"(patpix[i][0]),
305 /* %1 */ "r"(patpix[i+2048][0]),
306 /* %2 */ "r"(1024*64)
307 : /* clobbers */
308 "r0", "r1"
310 #elif defined(CPU_COLDFIRE)
311 asm volatile (
312 "movem.l (%0),%%d0-%%d3 \n"
313 "move.l %%d0,%%d4 \n"
314 "move.l %%d1,%%d5 \n"
315 "movem.l %%d2-%%d5,(48,%1) \n"
316 "movem.l (16,%0),%%d0-%%d3 \n"
317 "move.l %%d0,%%d4 \n"
318 "move.l %%d1,%%d5 \n"
319 "movem.l %%d2-%%d5,(32,%1) \n"
320 "movem.l (32,%0),%%d0-%%d3 \n"
321 "move.l %%d0,%%d4 \n"
322 "move.l %%d1,%%d5 \n"
323 "movem.l %%d2-%%d5,(16,%1) \n"
324 "movem.l (48,%0),%%d0-%%d3 \n"
325 "move.l %%d0,%%d4 \n"
326 "move.l %%d1,%%d5 \n"
327 "movem.l %%d2-%%d5,(%1) \n"
329 "move.l %2,%%d0 \n"
330 "add.l %%d0,%0 \n"
331 "add.l %%d0,%1 \n"
333 "movem.l (%0),%%d0-%%d3 \n"
334 "move.l %%d0,%%d4 \n"
335 "move.l %%d1,%%d5 \n"
336 "movem.l %%d2-%%d5,(48,%1) \n"
337 "movem.l (16,%0),%%d0-%%d3 \n"
338 "move.l %%d0,%%d4 \n"
339 "move.l %%d1,%%d5 \n"
340 "movem.l %%d2-%%d5,(32,%1) \n"
341 "movem.l (32,%0),%%d0-%%d3 \n"
342 "move.l %%d0,%%d4 \n"
343 "move.l %%d1,%%d5 \n"
344 "movem.l %%d2-%%d5,(16,%1) \n"
345 "movem.l (48,%0),%%d0-%%d3 \n"
346 "move.l %%d0,%%d4 \n"
347 "move.l %%d1,%%d5 \n"
348 "movem.l %%d2-%%d5,(%1) \n"
349 : /* outputs */
350 : /* inputs */
351 /* %0 */ "a"(patpix[i][0]),
352 /* %1 */ "a"(patpix[i+2048][0]),
353 /* %2 */ "i"(1024*64)
354 : /* clobbers */
355 "d0", "d1", "d2", "d3", "d4", "d5"
357 #else
358 for (j = 0; j < 8; j++)
360 for (k = 0; k < 8; k++)
362 patpix[i+2048][j][k] =
363 patpix[i][7-j][k];
364 patpix[i+3072][j][k] =
365 patpix[i+1024][7-j][k];
368 #endif
370 anydirty = 0;
372 #endif /* ASM_UPDATEPATPIX */
376 static void tilebuf(void) ICODE_ATTR;
377 static void tilebuf(void)
379 int i, cnt;
380 int base;
381 byte *tilemap, *attrmap;
382 int *tilebuf;
383 int *wrap;
384 static int wraptable[64] =
386 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
387 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,-32
390 base = ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5) + S;
391 tilemap = lcd.vbank[0] + base;
392 attrmap = lcd.vbank[1] + base;
393 tilebuf = BG;
394 wrap = wraptable + S;
395 cnt = ((WX + 7) >> 3) + 1;
397 if (hw.cgb) {
398 if (R_LCDC & 0x10)
399 for (i = cnt; i > 0; i--)
401 *(tilebuf++) = *tilemap
402 | (((int)*attrmap & 0x08) << 6)
403 | (((int)*attrmap & 0x60) << 5);
404 *(tilebuf++) = (((int)*attrmap & 0x07) << 2);
405 attrmap += *wrap + 1;
406 tilemap += *(wrap++) + 1;
408 else
409 for (i = cnt; i > 0; i--)
411 *(tilebuf++) = (256 + ((n8)*tilemap))
412 | (((int)*attrmap & 0x08) << 6)
413 | (((int)*attrmap & 0x60) << 5);
414 *(tilebuf++) = (((int)*attrmap & 0x07) << 2);
415 attrmap += *wrap + 1;
416 tilemap += *(wrap++) + 1;
419 else
421 if (R_LCDC & 0x10)
422 for (i = cnt; i > 0; i--)
424 *(tilebuf++) = *(tilemap++);
425 tilemap += *(wrap++);
427 else
428 for (i = cnt; i > 0; i--)
430 *(tilebuf++) = (256 + ((n8)*(tilemap++)));
431 tilemap += *(wrap++);
435 if (WX >= 160) return;
437 base = ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5);
438 tilemap = lcd.vbank[0] + base;
439 attrmap = lcd.vbank[1] + base;
440 tilebuf = WND;
441 cnt = ((160 - WX) >> 3) + 1;
443 if (hw.cgb)
445 if (R_LCDC & 0x10)
446 for (i = cnt; i > 0; i--)
448 *(tilebuf++) = *(tilemap++)
449 | (((int)*attrmap & 0x08) << 6)
450 | (((int)*attrmap & 0x60) << 5);
451 *(tilebuf++) = (((int)*(attrmap++)&7) << 2);
453 else
454 for (i = cnt; i > 0; i--)
456 *(tilebuf++) = (256 + ((n8)*(tilemap++)))
457 | (((int)*attrmap & 0x08) << 6)
458 | (((int)*attrmap & 0x60) << 5);
459 *(tilebuf++) = (((int)*(attrmap++)&7) << 2);
462 else
465 if (R_LCDC & 0x10)
466 for (i = cnt; i > 0; i--)
467 *(tilebuf++) = *(tilemap++);
468 else
469 for (i = cnt; i > 0; i--)
470 *(tilebuf++) = (256 + ((n8)*(tilemap++)));
475 /* V = vertical line
476 * WX = WND start (if 0, no need to do anything) -> WY
477 * U = start...something...thingy... 7 at most
479 static void bg_scan(void) ICODE_ATTR;
480 static void bg_scan(void)
482 int cnt;
483 byte *src, *dest;
484 int *tile;
486 if (WX <= 0) return;
487 cnt = WX;
488 tile = BG;
489 dest = BUF;
491 src = patpix[*(tile++)][V] + U;
492 memcpy(dest, src, 8-U);
493 dest += 8-U;
494 cnt -= 8-U;
495 if (cnt <= 0) return;
496 while (cnt >= 8)
498 #if defined(CPU_COLDFIRE)
499 asm volatile (
500 "move.l (%1)+,(%0)+ \n"
501 "move.l (%1)+,(%0)+ \n"
502 : /*outputs*/
503 : /*inputs*/
504 /* %0 */ "a" (dest),
505 /* %1 */ "a" (patpix[*(tile++)][V])
506 //: /* clobbers */
508 #else
509 src = patpix[*(tile++)][V];
510 memcpy(dest,src,8);
511 dest += 8;
512 #endif
513 cnt -= 8;
515 src = patpix[*tile][V];
516 while (cnt--)
517 *(dest++) = *(src++);
520 static void wnd_scan(void) ICODE_ATTR;
521 static void wnd_scan(void)
523 int cnt;
524 byte *src, *dest;
525 int *tile;
527 if (WX >= 160) return;
528 cnt = 160 - WX;
529 tile = WND;
530 dest = BUF + WX;
532 while (cnt >= 8)
534 #if defined(CPU_COLDFIRE)
535 asm volatile (
536 "move.l (%1)+,(%0)+ \n"
537 "move.l (%1)+,(%0)+ \n"
538 : /*outputs*/
539 : /*inputs*/
540 /* %0 */ "a" (dest),
541 /* %1 */ "a" (patpix[*(tile++)][WV])
542 //: /* clobbers */
544 #else
545 src = patpix[*(tile++)][WV];
546 memcpy(dest,src,8);
547 dest += 8;
548 #endif
549 cnt -= 8;
551 src = patpix[*tile][WV];
552 while (cnt--)
553 *(dest++) = *(src++);
556 static void blendcpy(byte *dest, byte *src, byte b, int cnt)
558 while (cnt--) *(dest++) = *(src++) | b;
561 static int priused(void *attr)
563 un32 *a = attr;
564 return (int)((a[0]|a[1]|a[2]|a[3]|a[4]|a[5]|a[6]|a[7])&0x80808080);
567 static void bg_scan_pri(void) ICODE_ATTR;
568 static void bg_scan_pri(void)
570 int cnt, i;
571 byte *src, *dest;
573 if (WX <= 0) return;
574 i = S;
575 cnt = WX;
576 dest = PRI;
577 src = lcd.vbank[1] + ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5);
579 if (!priused(src))
581 memset(dest, 0, cnt);
582 return;
585 memset(dest, src[i++&31]&128, 8-U);
586 dest += 8-U;
587 cnt -= 8-U;
588 if (cnt <= 0) return;
589 while (cnt >= 8)
591 memset(dest, src[i++&31]&128, 8);
592 dest += 8;
593 cnt -= 8;
595 memset(dest, src[i&31]&128, cnt);
598 static void wnd_scan_pri(void) ICODE_ATTR;
599 static void wnd_scan_pri(void)
601 int cnt, i;
602 byte *src, *dest;
604 if (WX >= 160) return;
605 i = 0;
606 cnt = 160 - WX;
607 dest = PRI + WX;
608 src = lcd.vbank[1] + ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5);
610 if (!priused(src))
612 memset(dest, 0, cnt);
613 return;
616 while (cnt >= 8)
618 memset(dest, src[i++]&128, 8);
619 dest += 8;
620 cnt -= 8;
622 memset(dest, src[i]&128, cnt);
625 static void bg_scan_color(void)
627 int cnt;
628 byte *src, *dest;
629 int *tile;
631 if (WX <= 0) return;
632 cnt = WX;
633 tile = BG;
634 dest = BUF;
636 src = patpix[*(tile++)][V] + U;
637 blendcpy(dest, src, *(tile++), 8-U);
638 dest += 8-U;
639 cnt -= 8-U;
640 if (cnt <= 0) return;
641 while (cnt >= 8)
643 src = patpix[*(tile++)][V];
644 #if defined(CPU_COLDFIRE)
645 asm volatile (
646 "move.l (%2)+,%%d1 \n"
648 "move.b %%d1,%%d2 \n"
650 "move.b (%1)+,%%d0 \n"
651 "or.l %%d2,%%d0 \n"
652 "move.b %%d0,(%0)+ \n"
654 "move.b (%1)+,%%d0 \n"
655 "or.l %%d1,%%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"
678 "move.b (%1)+,%%d0 \n"
679 "or.l %%d2,%%d0 \n"
680 "move.b %%d0,(%0)+ \n"
681 : /*outputs*/
682 : /*inputs*/
683 /* %0 */ "a" (dest),
684 /* %1 */ "a" (src),
685 /* %2 */ "a" (tile)
686 : /* clobbers */
687 "d0", "d1", "d2"
689 #else
690 blendcpy(dest, src, *(tile++), 8);
691 dest += 8;
692 #endif
693 cnt -= 8;
695 src = patpix[*(tile++)][V];
696 blendcpy(dest, src, *(tile++), cnt);
699 static void wnd_scan_color(void)
701 int cnt;
702 byte *src, *dest;
703 int *tile;
705 if (WX >= 160) return;
706 cnt = 160 - WX;
707 tile = WND;
708 dest = BUF + WX;
710 while (cnt >= 8)
712 src = patpix[*(tile++)][WV];
713 blendcpy(dest, src, *(tile++), 8);
714 dest += 8;
715 cnt -= 8;
717 src = patpix[*(tile++)][WV];
718 blendcpy(dest, src, *(tile++), cnt);
721 static void spr_enum(void) ICODE_ATTR;
722 static void spr_enum(void)
724 int i, j;
725 struct obj *o;
726 struct vissprite ts;
727 int v, pat;
729 NS = 0;
730 if (!(R_LCDC & 0x02)) return;
732 o = lcd.oam.obj;
734 for (i = 40; i; i--, o++)
736 if (L >= o->y || L + 16 < o->y)
737 continue;
738 if (L + 8 >= o->y && !(R_LCDC & 0x04))
739 continue;
740 VS[NS].x = (int)o->x - 8;
741 v = L - (int)o->y + 16;
742 if (hw.cgb)
744 pat = o->pat | (((int)o->flags & 0x60) << 5)
745 | (((int)o->flags & 0x08) << 6);
746 VS[NS].pal = 32 + ((o->flags & 0x07) << 2);
748 else
750 pat = o->pat | (((int)o->flags & 0x60) << 5);
751 VS[NS].pal = 32 + ((o->flags & 0x10) >> 2);
753 VS[NS].pri = (o->flags & 0x80) >> 7;
754 if ((R_LCDC & 0x04))
756 pat &= ~1;
757 if (v >= 8)
759 v -= 8;
760 pat++;
762 if (o->flags & 0x40) pat ^= 1;
764 VS[NS].buf = patpix[pat][v];
765 if (++NS == 10) break;
767 if (hw.cgb) return;
768 for (i = 0; i < NS; i++)
770 for (j = i + 1; j < NS; j++)
772 if (VS[i].x > VS[j].x)
774 ts = VS[i];
775 VS[i] = VS[j];
776 VS[j] = ts;
782 static void spr_scan(void) ICODE_ATTR;
783 static void spr_scan(void)
785 int i, x;
786 byte pal, b, ns = NS;
787 byte *src, *dest, *bg, *pri;
788 struct vissprite *vs;
789 static byte bgdup[256];
791 if (!ns) return;
793 memcpy(bgdup, BUF, 256);
794 vs = &VS[ns-1];
796 for (; ns; ns--, vs--)
798 x = vs->x;
799 if (x > 159) continue;
800 if (x < -7) continue;
801 if (x < 0)
803 src = vs->buf - x;
804 dest = BUF;
805 i = 8 + x;
807 else
809 src = vs->buf;
810 dest = BUF + x;
811 if (x > 152) i = 160 - x;
812 else i = 8;
814 pal = vs->pal;
815 if (vs->pri)
817 bg = bgdup + (dest - BUF);
818 while (i--)
820 b = src[i];
821 if (b && !(bg[i]&3)) dest[i] = pal|b;
824 else if (hw.cgb)
826 bg = bgdup + (dest - BUF);
827 pri = PRI + (dest - BUF);
828 while (i--)
830 b = src[i];
831 if (b && (!pri[i] || !(bg[i]&3)))
832 dest[i] = pal|b;
835 else while (i--) if (src[i]) dest[i] = pal|src[i];
839 /* Scaling defines */
840 #define DX ((LCD_WIDTH<<16) / 160)
841 #define DXI ((160<<16) / LCD_WIDTH)
842 #define DY ((LCD_HEIGHT<<16) / 144)
843 #define DYI ((144<<16) / LCD_HEIGHT)
845 #define DXR ((LCD_WIDTH<<16) / 144)
846 #define DXIR ((144<<16) / LCD_WIDTH)
847 #define DYR ((LCD_HEIGHT<<16) / 160)
848 #define DYIR ((160<<16) / LCD_HEIGHT)
850 /* Defines for scale offsets:
851 * S2 is for scaled
852 * S3 if scaled and maintain ratio
853 * S1 is unscaled
854 * R's are the rotated defines
856 #if (LCD_WIDTH>=160) && (LCD_HEIGHT>=144)
857 #define S1 ((LCD_HEIGHT-144)/2)*LCD_WIDTH + ((LCD_WIDTH-160)/2)
858 #define S2 0
859 #define S1R ((LCD_HEIGHT-160)/2)*LCD_WIDTH + ((LCD_WIDTH-144)/2)+144
860 #define S2R (LCD_WIDTH-1)
862 #elif (LCD_WIDTH>=160) && (LCD_HEIGHT<=144)
863 #define S1 0
864 #define S2 0
865 #define S1R LCD_WIDTH-1
866 #define S2R LCD_WIDTH-1
868 #elif (LCD_WIDTH<=160) && (LCD_HEIGHT>=144)
869 #define S1 ((LCD_HEIGHT-144)/2)*LCD_WIDTH
870 #define S2 ((LCD_HEIGHT-144)/2)*LCD_WIDTH
871 #define S1R LCD_WIDTH-1
872 #define S2R LCD_WIDTH-1
874 #else
875 #define S1 0
876 #define S2 0
877 #define S1R LCD_WIDTH-1
878 #define S2R LCD_WIDTH-1
879 #endif
881 #if (LCD_WIDTH>LCD_HEIGHT)
882 #define S3 ((LCD_WIDTH-((160*DY)>>16))/2)
883 #define S3R LCD_WIDTH-1
884 #else
885 #define S3 ((LCD_HEIGHT-((144*DX)>>16))/2)*LCD_WIDTH
886 #define S3R ((LCD_HEIGHT-((160*DXR)>>16))/2)*LCD_WIDTH+LCD_WIDTH-1
887 #endif
889 void lcd_begin(void)
891 #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
892 vdest=(unsigned char*)rb->lcd_framebuffer;
893 #else
894 vdest=rb->lcd_framebuffer;
895 #endif
897 #ifdef HAVE_LCD_COLOR
899 if(options.rotate==1) {
900 if(options.scaling == 0)
901 vdest+=S2R;
902 else if (options.scaling == 1)
903 vdest+=S3R;
904 else
905 vdest+=S1R;
906 } else if(options.rotate==2) {
907 if(options.scaling == 0)
908 vdest+=(LCD_WIDTH*LCD_HEIGHT)-S2R;
909 else if (options.scaling == 1)
910 vdest+=(LCD_WIDTH*LCD_HEIGHT)-S3R;
911 else
912 vdest+=(LCD_WIDTH*LCD_HEIGHT)-S1R-144;
913 } else {
914 if(options.scaling == 0)
915 vdest+=S2;
916 else if (options.scaling == 1)
917 vdest+=S3;
918 else
919 vdest+=S1;
921 #endif
922 WY = R_WY;
925 #ifdef HAVE_LCD_COLOR
926 int SCALEWL IDATA_ATTR=1<<16;
927 int SCALEWS IDATA_ATTR=1<<16;
928 int SCALEHL IDATA_ATTR=1<<16;
929 int SCALEHS IDATA_ATTR=1<<16;
930 int swidth IDATA_ATTR=160;
931 int sremain IDATA_ATTR=LCD_WIDTH-160;
932 #endif
934 void setvidmode(void)
937 #ifdef HAVE_LCD_COLOR
938 switch(options.scaling)
940 case 0:
941 if(options.rotate)
943 SCALEWL=DYR;
944 SCALEWS=DYIR;
945 SCALEHL=DXR;
946 SCALEHS=DXIR;
948 else
950 SCALEWL=DX;
951 SCALEWS=DXI;
952 SCALEHL=DY;
953 SCALEHS=DYI;
955 break;
956 case 1: /* Maintain Ratio */
957 if(options.rotate)
959 if (DYR<DXR)
961 SCALEWL=DYR;
962 SCALEWS=DYIR;
963 SCALEHL=DYR;
964 SCALEHS=DYIR;
966 else
968 SCALEWL=DXR;
969 SCALEWS=DXIR;
970 SCALEHL=DXR;
971 SCALEHS=DXIR;
974 else
976 if (DY<DX)
978 SCALEWL=DY;
979 SCALEWS=DYI;
980 SCALEHL=DY;
981 SCALEHS=DYI;
983 else
985 SCALEWL=DX;
986 SCALEWS=DXI;
987 SCALEHL=DX;
988 SCALEHS=DXI;
991 break;
992 default:
993 SCALEWL=1<<16;
994 SCALEWS=1<<16;
995 SCALEHL=1<<16;
996 SCALEHS=1<<16;
998 swidth=((160*SCALEWL)>>16);
1000 if(options.rotate==1) {
1001 sremain=-(((160*SCALEWL)>>16)*LCD_WIDTH+1);
1002 } else if(options.rotate==2) {
1003 sremain=(((160*SCALEWL)>>16)*LCD_WIDTH+1);
1004 } else {
1005 sremain=LCD_WIDTH-swidth;
1007 #endif
1010 void lcd_refreshline(void)
1012 if (!(R_LCDC & 0x80))
1013 return; /* should not happen... */
1015 #if (LCD_HEIGHT <= 128) && !defined(HAVE_LCD_COLOR)
1016 if ( (fb.mode==0&&(R_LY >= 128)) ||
1017 (fb.mode==1&&(R_LY < 16)) ||
1018 (fb.mode==2&&(R_LY<8||R_LY>=136)) ||
1019 (fb.mode==3&&((R_LY%9)==8))
1021 #if LCD_HEIGHT == 64
1022 || (R_LY & 1) /* calculate only even lines */
1023 #endif
1025 return;
1026 #endif
1028 updatepatpix();
1030 L = R_LY;
1031 X = R_SCX;
1032 Y = (R_SCY + L) & 0xff;
1033 S = X >> 3;
1034 T = Y >> 3;
1035 U = X & 7;
1036 V = Y & 7;
1038 WX = R_WX - 7;
1039 if (WY>L || WY<0 || WY>143 || WX<-7 || WX>159 || !(R_LCDC&0x20))
1040 WX = 160;
1041 WT = (L - WY) >> 3;
1042 WV = (L - WY) & 7;
1044 spr_enum();
1046 tilebuf();
1047 if (hw.cgb)
1049 bg_scan_color();
1050 wnd_scan_color();
1051 if (NS)
1053 bg_scan_pri();
1054 wnd_scan_pri();
1057 else
1060 bg_scan();
1061 wnd_scan();
1063 spr_scan();
1065 #if !defined(HAVE_LCD_COLOR)
1066 #if LCD_DEPTH == 1
1067 if (scanline_ind == 7)
1068 #elif LCD_DEPTH == 2
1069 if (scanline_ind == 3)
1070 #endif
1072 if(fb.mode!=3)
1073 vid_update(L);
1074 else
1075 vid_update(L-((int)(L/9)));
1076 #else
1078 /* Universal Scaling pulled from PrBoom and modified for rockboy */
1080 static int hpt IDATA_ATTR=0x8000;
1082 while((hpt>>16)<L+1)
1084 hpt+=SCALEHS;
1085 register unsigned int srcpt=0x8000;
1086 register unsigned int wcount=swidth;
1087 while(wcount--)
1089 #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
1090 *vdest = BUF[srcpt>>16];
1091 #else
1092 *vdest = PAL[BUF[srcpt>>16]];
1093 #endif
1094 if (options.rotate == 1) {
1095 vdest+=LCD_WIDTH;
1096 } else if (options.rotate == 2) {
1097 vdest-=LCD_WIDTH;
1098 } else {
1099 vdest++;
1102 srcpt+=SCALEWS;
1104 vdest+=sremain;
1107 if(L==143)
1109 if(options.showstats)
1111 if(options.showstats==1) {
1112 rb->lcd_putsxyf(0,LCD_HEIGHT-10," %d %d ",
1113 options.fps, options.frameskip);
1114 } else {
1115 rb->lcd_putsxyf(0,LCD_HEIGHT-10," FPS: %d Frameskip: %d ",
1116 options.fps, options.frameskip);
1118 rb->lcd_update_rect(0,LCD_HEIGHT-10, LCD_WIDTH, 10);
1121 hpt=0x8000;
1123 #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
1124 if(options.scaling==3) {
1125 rb->lcd_blit_pal256((unsigned char*)rb->lcd_framebuffer,(LCD_WIDTH-160)/2, (LCD_HEIGHT-144)/2, (LCD_WIDTH-160)/2, (LCD_HEIGHT-144)/2, 160, 144);
1126 } else {
1127 rb->lcd_blit_pal256((unsigned char*)rb->lcd_framebuffer,0,0,0,0,LCD_WIDTH,LCD_HEIGHT);
1129 #else
1130 if(options.scaling==3) {
1131 rb->lcd_update_rect( (LCD_WIDTH-160)/2, (LCD_HEIGHT-144)/2, 160, 144);
1132 } else {
1133 rb->lcd_update();
1135 #endif
1138 #endif
1140 #if LCD_DEPTH == 1
1141 scanline_ind = (scanline_ind+1) % 8;
1142 #elif LCD_DEPTH == 2
1143 scanline_ind = (scanline_ind+1) % 4;
1144 #endif
1147 #ifdef HAVE_LCD_COLOR
1148 void set_pal(void)
1150 memcpy(dmg_pal,palettes[options.pal], sizeof(dmg_pal));
1151 pal_dirty();
1154 static void updatepalette(int i)
1156 int c, r, g, b;
1158 c = (lcd.pal[i<<1] | ((int)lcd.pal[(i<<1)|1] << 8)) & 0x7FFF;
1159 r = (c & 0x001F) << 3;
1160 g = (c & 0x03E0) >> 2;
1161 b = (c & 0x7C00) >> 7;
1162 r |= (r >> 5);
1163 g |= (g >> 5);
1164 b |= (b >> 5);
1166 r = (r >> fb.cc[0].r) << fb.cc[0].l;
1167 g = (g >> fb.cc[1].r) << fb.cc[1].l;
1168 b = (b >> fb.cc[2].r) << fb.cc[2].l;
1170 #if LCD_PIXELFORMAT == RGB565
1171 c = r|g|b;
1172 #elif LCD_PIXELFORMAT == RGB565SWAPPED
1173 c = swap16(r|g|b);
1174 #endif
1176 /* updatepalette might get called, but the pallete does not necessarily
1177 * need to be updated.
1179 if(PAL[i]!=c)
1181 PAL[i] = c;
1182 #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
1183 rb->lcd_pal256_update_pal(PAL);
1184 #endif
1187 #endif /* HAVE_LCD_COLOR */
1189 void pal_write(int i, byte b)
1191 if (lcd.pal[i] == b) return;
1192 lcd.pal[i] = b;
1193 #ifdef HAVE_LCD_COLOR
1194 updatepalette(i>>1);
1195 #endif
1198 void pal_write_dmg(int i, int mapnum, byte d)
1200 int j;
1201 int *cmap = dmg_pal[mapnum];
1202 int c, r, g, b;
1204 if (hw.cgb) return;
1206 for (j = 0; j < 8; j += 2)
1208 c = cmap[(d >> j) & 3];
1209 r = (c & 0xf8) >> 3;
1210 g = (c & 0xf800) >> 6;
1211 b = (c & 0xf80000) >> 9;
1212 c = r|g|b;
1213 /* FIXME - handle directly without faking cgb */
1214 pal_write(i+j, c & 0xff);
1215 pal_write(i+j+1, c >> 8);
1219 void vram_write(addr a, byte b)
1221 lcd.vbank[R_VBK&1][a] = b;
1222 if (a >= 0x1800) return;
1223 patdirty[((R_VBK&1)<<9)+(a>>4)] = 1;
1224 anydirty = 1;
1225 pal_dirty();
1228 void vram_dirty(void)
1230 anydirty = 1;
1231 memset(patdirty, 1, sizeof patdirty);
1234 void pal_dirty(void)
1236 #ifdef HAVE_LCD_COLOR
1237 int i;
1238 #endif
1239 if (!hw.cgb)
1242 pal_write_dmg(0, 0, R_BGP);
1243 pal_write_dmg(8, 1, R_BGP);
1244 pal_write_dmg(64, 2, R_OBP0);
1245 pal_write_dmg(72, 3, R_OBP1);
1247 #ifdef HAVE_LCD_COLOR
1248 for (i = 0; i < 64; i++)
1249 updatepalette(i);
1250 #endif
1253 void lcd_reset(void)
1255 memset(&lcd, 0, sizeof lcd);
1256 lcd_begin();
1257 vram_dirty();