A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
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
14
15struct lcd lcd;
16
17struct scan scan IBSS_ATTR;
18
19#define BG (scan.bg)
20#define WND (scan.wnd)
21
22#if LCD_DEPTH >= 16
23#define BUF (scan.buf)
24#else
25#define BUF (scan.buf[scanline_ind])
26#endif
27
28#define PRI (scan.pri)
29
30#define PAL (scan.pal)
31
32#define VS (scan.vs) /* vissprites */
33#define NS (scan.ns)
34
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)
46
47byte patpix[4096][8][8]
48#if defined(CPU_COLDFIRE)
49 __attribute__ ((aligned(16))) /* to profit from burst mode */
50#endif
51 ;
52byte patdirty[1024];
53byte anydirty;
54
55#if LCD_DEPTH < 16
56static int scanline_ind=0;
57#endif
58
59static int dmg_pal[4][4];
60
61#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
62unsigned char *vdest;
63#else
64fb_data *vdest;
65#endif
66
67static fb_data* get_framebuffer(void)
68{
69 struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport);
70 return vp_main->buffer->fb_ptr;
71}
72
73#ifndef ASM_UPDATEPATPIX
74static void updatepatpix(void) ICODE_ATTR;
75static void updatepatpix(void)
76{
77 int i, j;
78#if !defined(CPU_COLDFIRE)
79 int k, a, c;
80#endif
81 byte *vram = lcd.vbank[0];
82
83 if (!anydirty) return;
84 for (i = 0; i < 1024; i++)
85 {
86 if (i == 384) i = 512;
87 if (i == 896) break;
88 if (!patdirty[i]) continue;
89 patdirty[i] = 0;
90 for (j = 0; j < 8; j++)
91 {
92#if defined(CPU_COLDFIRE)
93 asm volatile (
94 "move.b (%2),%%d2 \n"
95 "move.b (1,%2),%%d1 \n"
96
97 "addq.l #8,%1 \n"
98 "clr.l %%d0 \n"
99 "lsr.l #1,%%d1 \n"
100 "addx.l %%d0,%%d0 \n"
101 "lsr.l #1,%%d2 \n"
102 "addx.l %%d0,%%d0 \n"
103 "move.b %%d0,-(%1) \n"
104 "lsl.l #6,%%d0 \n"
105 "lsr.l #1,%%d1 \n"
106 "addx.l %%d0,%%d0 \n"
107 "lsr.l #1,%%d2 \n"
108 "addx.l %%d0,%%d0 \n"
109 "move.b %%d0,-(%1) \n"
110 "lsl.l #6,%%d0 \n"
111 "lsr.l #1,%%d1 \n"
112 "addx.l %%d0,%%d0 \n"
113 "lsr.l #1,%%d2 \n"
114 "addx.l %%d0,%%d0 \n"
115 "move.b %%d0,-(%1) \n"
116 "lsl.l #6,%%d0 \n"
117 "lsr.l #1,%%d1 \n"
118 "addx.l %%d0,%%d0 \n"
119 "lsr.l #1,%%d2 \n"
120 "addx.l %%d0,%%d0 \n"
121 "move.l %%d0,(%0) \n"
122 "move.b %%d0,-(%1) \n"
123 "clr.l %%d0 \n"
124 "lsr.l #1,%%d1 \n"
125 "addx.l %%d0,%%d0 \n"
126 "lsr.l #1,%%d2 \n"
127 "addx.l %%d0,%%d0 \n"
128 "move.b %%d0,-(%1) \n"
129 "lsl.l #6,%%d0 \n"
130 "lsr.l #1,%%d1 \n"
131 "addx.l %%d0,%%d0 \n"
132 "lsr.l #1,%%d2 \n"
133 "addx.l %%d0,%%d0 \n"
134 "move.b %%d0,-(%1) \n"
135 "lsl.l #6,%%d0 \n"
136 "lsr.l #1,%%d1 \n"
137 "addx.l %%d0,%%d0 \n"
138 "lsr.l #1,%%d2 \n"
139 "addx.l %%d0,%%d0 \n"
140 "move.b %%d0,-(%1) \n"
141 "lsl.l #6,%%d0 \n"
142 "lsr.l #1,%%d1 \n"
143 "addx.l %%d0,%%d0 \n"
144 "lsr.l #1,%%d2 \n"
145 "addx.l %%d0,%%d0 \n"
146 "move.l %%d0,(4,%0) \n"
147 "move.b %%d0,-(%1) \n"
148 : /* outputs */
149 : /* inputs */
150 /* %0 */ "a"(patpix[i+1024][j]),
151 /* %1 */ "a"(patpix[i][j]),
152 /* %2 */ "a"(&vram[(i<<4)|(j<<1)])
153 : /* clobbers */
154 "d0", "d1", "d2"
155 );
156#else
157 a = ((i<<4) | (j<<1));
158 for (k = 0; k < 8; k++)
159 {
160 c = vram[a] & BIT_N(k) ? 1 : 0;
161 c |= vram[a+1] & BIT_N(k) ? 2 : 0;
162 patpix[i+1024][j][k] = c;
163 }
164 for (k = 0; k < 8; k++)
165 patpix[i][j][k] =
166 patpix[i+1024][j][7-k];
167#endif
168 }
169#if defined(CPU_COLDFIRE)
170 asm volatile (
171 "movem.l (%0),%%d0-%%d3 \n"
172 "move.l %%d0,%%d4 \n"
173 "move.l %%d1,%%d5 \n"
174 "movem.l %%d2-%%d5,(48,%1) \n"
175 "movem.l (16,%0),%%d0-%%d3 \n"
176 "move.l %%d0,%%d4 \n"
177 "move.l %%d1,%%d5 \n"
178 "movem.l %%d2-%%d5,(32,%1) \n"
179 "movem.l (32,%0),%%d0-%%d3 \n"
180 "move.l %%d0,%%d4 \n"
181 "move.l %%d1,%%d5 \n"
182 "movem.l %%d2-%%d5,(16,%1) \n"
183 "movem.l (48,%0),%%d0-%%d3 \n"
184 "move.l %%d0,%%d4 \n"
185 "move.l %%d1,%%d5 \n"
186 "movem.l %%d2-%%d5,(%1) \n"
187
188 "move.l %2,%%d0 \n"
189 "add.l %%d0,%0 \n"
190 "add.l %%d0,%1 \n"
191
192 "movem.l (%0),%%d0-%%d3 \n"
193 "move.l %%d0,%%d4 \n"
194 "move.l %%d1,%%d5 \n"
195 "movem.l %%d2-%%d5,(48,%1) \n"
196 "movem.l (16,%0),%%d0-%%d3 \n"
197 "move.l %%d0,%%d4 \n"
198 "move.l %%d1,%%d5 \n"
199 "movem.l %%d2-%%d5,(32,%1) \n"
200 "movem.l (32,%0),%%d0-%%d3 \n"
201 "move.l %%d0,%%d4 \n"
202 "move.l %%d1,%%d5 \n"
203 "movem.l %%d2-%%d5,(16,%1) \n"
204 "movem.l (48,%0),%%d0-%%d3 \n"
205 "move.l %%d0,%%d4 \n"
206 "move.l %%d1,%%d5 \n"
207 "movem.l %%d2-%%d5,(%1) \n"
208 : /* outputs */
209 : /* inputs */
210 /* %0 */ "a"(patpix[i][0]),
211 /* %1 */ "a"(patpix[i+2048][0]),
212 /* %2 */ "i"(1024*64)
213 : /* clobbers */
214 "d0", "d1", "d2", "d3", "d4", "d5"
215 );
216#else
217 for (j = 0; j < 8; j++)
218 {
219 for (k = 0; k < 8; k++)
220 {
221 patpix[i+2048][j][k] =
222 patpix[i][7-j][k];
223 patpix[i+3072][j][k] =
224 patpix[i+1024][7-j][k];
225 }
226 }
227#endif
228 }
229 anydirty = 0;
230}
231#endif /* ASM_UPDATEPATPIX */
232
233
234
235static void tilebuf(void) ICODE_ATTR;
236static void tilebuf(void)
237{
238 int i, cnt;
239 int base;
240 byte *tilemap, *attrmap;
241 int *tilebuf;
242 int *wrap;
243 static int wraptable[64] =
244 {
245 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
246 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,-32
247 };
248
249 base = ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5) + S;
250 tilemap = lcd.vbank[0] + base;
251 attrmap = lcd.vbank[1] + base;
252 tilebuf = BG;
253 wrap = wraptable + S;
254 cnt = ((WX + 7) >> 3) + 1;
255
256 if (hw.cgb) {
257 if (R_LCDC & 0x10)
258 for (i = cnt; i > 0; i--)
259 {
260 *(tilebuf++) = *tilemap
261 | (((int)*attrmap & 0x08) << 6)
262 | (((int)*attrmap & 0x60) << 5);
263 *(tilebuf++) = (((int)*attrmap & 0x07) << 2);
264 attrmap += *wrap + 1;
265 tilemap += *(wrap++) + 1;
266 }
267 else
268 for (i = cnt; i > 0; i--)
269 {
270 *(tilebuf++) = (256 + ((n8)*tilemap))
271 | (((int)*attrmap & 0x08) << 6)
272 | (((int)*attrmap & 0x60) << 5);
273 *(tilebuf++) = (((int)*attrmap & 0x07) << 2);
274 attrmap += *wrap + 1;
275 tilemap += *(wrap++) + 1;
276 }
277 }
278 else
279 {
280 if (R_LCDC & 0x10)
281 for (i = cnt; i > 0; i--)
282 {
283 *(tilebuf++) = *(tilemap++);
284 tilemap += *(wrap++);
285 }
286 else
287 for (i = cnt; i > 0; i--)
288 {
289 *(tilebuf++) = (256 + ((n8)*(tilemap++)));
290 tilemap += *(wrap++);
291 }
292 }
293
294 if (WX >= 160) return;
295
296 base = ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5);
297 tilemap = lcd.vbank[0] + base;
298 attrmap = lcd.vbank[1] + base;
299 tilebuf = WND;
300 cnt = ((160 - WX) >> 3) + 1;
301
302 if (hw.cgb)
303 {
304 if (R_LCDC & 0x10)
305 for (i = cnt; i > 0; i--)
306 {
307 *(tilebuf++) = *(tilemap++)
308 | (((int)*attrmap & 0x08) << 6)
309 | (((int)*attrmap & 0x60) << 5);
310 *(tilebuf++) = (((int)*(attrmap++)&7) << 2);
311 }
312 else
313 for (i = cnt; i > 0; i--)
314 {
315 *(tilebuf++) = (256 + ((n8)*(tilemap++)))
316 | (((int)*attrmap & 0x08) << 6)
317 | (((int)*attrmap & 0x60) << 5);
318 *(tilebuf++) = (((int)*(attrmap++)&7) << 2);
319 }
320 }
321 else
322
323 {
324 if (R_LCDC & 0x10)
325 for (i = cnt; i > 0; i--)
326 *(tilebuf++) = *(tilemap++);
327 else
328 for (i = cnt; i > 0; i--)
329 *(tilebuf++) = (256 + ((n8)*(tilemap++)));
330 }
331}
332
333
334/* V = vertical line
335 * WX = WND start (if 0, no need to do anything) -> WY
336 * U = start...something...thingy... 7 at most
337 */
338static void bg_scan(void) ICODE_ATTR;
339static void bg_scan(void)
340{
341 int cnt;
342 byte *src, *dest;
343 int *tile;
344
345 if (WX <= 0) return;
346 cnt = WX;
347 tile = BG;
348 dest = BUF;
349
350 src = patpix[*(tile++)][V] + U;
351 memcpy(dest, src, 8-U);
352 dest += 8-U;
353 cnt -= 8-U;
354 if (cnt <= 0) return;
355 while (cnt >= 8)
356 {
357#if defined(CPU_COLDFIRE)
358 asm volatile (
359 "move.l (%1)+,(%0)+ \n"
360 "move.l (%1)+,(%0)+ \n"
361 : /*outputs*/
362 : /*inputs*/
363 /* %0 */ "a" (dest),
364 /* %1 */ "a" (patpix[*(tile++)][V])
365 //: /* clobbers */
366 );
367#else
368 src = patpix[*(tile++)][V];
369 memcpy(dest,src,8);
370 dest += 8;
371#endif
372 cnt -= 8;
373 }
374 src = patpix[*tile][V];
375 while (cnt--)
376 *(dest++) = *(src++);
377}
378
379static void wnd_scan(void) ICODE_ATTR;
380static void wnd_scan(void)
381{
382 int cnt;
383 byte *src, *dest;
384 int *tile;
385
386 if (WX >= 160) return;
387 cnt = 160 - WX;
388 tile = WND;
389 dest = BUF + WX;
390
391 while (cnt >= 8)
392 {
393#if defined(CPU_COLDFIRE)
394 asm volatile (
395 "move.l (%1)+,(%0)+ \n"
396 "move.l (%1)+,(%0)+ \n"
397 : /*outputs*/
398 : /*inputs*/
399 /* %0 */ "a" (dest),
400 /* %1 */ "a" (patpix[*(tile++)][WV])
401 //: /* clobbers */
402 );
403#else
404 src = patpix[*(tile++)][WV];
405 memcpy(dest,src,8);
406 dest += 8;
407#endif
408 cnt -= 8;
409 }
410 src = patpix[*tile][WV];
411 while (cnt--)
412 *(dest++) = *(src++);
413}
414
415static void blendcpy(byte *dest, byte *src, byte b, int cnt)
416{
417 while (cnt--) *(dest++) = *(src++) | b;
418}
419
420static int priused(void *attr)
421{
422 un32 *a = attr;
423 return (int)((a[0]|a[1]|a[2]|a[3]|a[4]|a[5]|a[6]|a[7])&0x80808080);
424}
425
426static void bg_scan_pri(void) ICODE_ATTR;
427static void bg_scan_pri(void)
428{
429 int cnt, i;
430 byte *src, *dest;
431
432 if (WX <= 0) return;
433 i = S;
434 cnt = WX;
435 dest = PRI;
436 src = lcd.vbank[1] + ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5);
437
438 if (!priused(src))
439 {
440 memset(dest, 0, cnt);
441 return;
442 }
443
444 memset(dest, src[i++&31]&128, 8-U);
445 dest += 8-U;
446 cnt -= 8-U;
447 if (cnt <= 0) return;
448 while (cnt >= 8)
449 {
450 memset(dest, src[i++&31]&128, 8);
451 dest += 8;
452 cnt -= 8;
453 }
454 memset(dest, src[i&31]&128, cnt);
455}
456
457static void wnd_scan_pri(void) ICODE_ATTR;
458static void wnd_scan_pri(void)
459{
460 int cnt, i;
461 byte *src, *dest;
462
463 if (WX >= 160) return;
464 i = 0;
465 cnt = 160 - WX;
466 dest = PRI + WX;
467 src = lcd.vbank[1] + ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5);
468
469 if (!priused(src))
470 {
471 memset(dest, 0, cnt);
472 return;
473 }
474
475 while (cnt >= 8)
476 {
477 memset(dest, src[i++]&128, 8);
478 dest += 8;
479 cnt -= 8;
480 }
481 memset(dest, src[i]&128, cnt);
482}
483
484static void bg_scan_color(void)
485{
486 int cnt;
487 byte *src, *dest;
488 int *tile;
489
490 if (WX <= 0) return;
491 cnt = WX;
492 tile = BG;
493 dest = BUF;
494
495 src = patpix[*(tile++)][V] + U;
496 blendcpy(dest, src, *(tile++), 8-U);
497 dest += 8-U;
498 cnt -= 8-U;
499 if (cnt <= 0) return;
500 while (cnt >= 8)
501 {
502 src = patpix[*(tile++)][V];
503#if defined(CPU_COLDFIRE)
504 asm volatile (
505 "move.l (%2)+,%%d1 \n"
506
507 "move.b %%d1,%%d2 \n"
508
509 "move.b (%1)+,%%d0 \n"
510 "or.l %%d2,%%d0 \n"
511 "move.b %%d0,(%0)+ \n"
512
513 "move.b (%1)+,%%d0 \n"
514 "or.l %%d1,%%d0 \n"
515 "move.b %%d0,(%0)+ \n"
516
517 "move.b (%1)+,%%d0 \n"
518 "or.l %%d2,%%d0 \n"
519 "move.b %%d0,(%0)+ \n"
520
521 "move.b (%1)+,%%d0 \n"
522 "or.l %%d2,%%d0 \n"
523 "move.b %%d0,(%0)+ \n"
524
525 "move.b (%1)+,%%d0 \n"
526 "or.l %%d2,%%d0 \n"
527 "move.b %%d0,(%0)+ \n"
528
529 "move.b (%1)+,%%d0 \n"
530 "or.l %%d2,%%d0 \n"
531 "move.b %%d0,(%0)+ \n"
532
533 "move.b (%1)+,%%d0 \n"
534 "or.l %%d2,%%d0 \n"
535 "move.b %%d0,(%0)+ \n"
536
537 "move.b (%1)+,%%d0 \n"
538 "or.l %%d2,%%d0 \n"
539 "move.b %%d0,(%0)+ \n"
540 : /*outputs*/
541 : /*inputs*/
542 /* %0 */ "a" (dest),
543 /* %1 */ "a" (src),
544 /* %2 */ "a" (tile)
545 : /* clobbers */
546 "d0", "d1", "d2"
547);
548#else
549 blendcpy(dest, src, *(tile++), 8);
550 dest += 8;
551#endif
552 cnt -= 8;
553 }
554 src = patpix[*(tile++)][V];
555 blendcpy(dest, src, *(tile++), cnt);
556}
557
558static void wnd_scan_color(void)
559{
560 int cnt;
561 byte *src, *dest;
562 int *tile;
563
564 if (WX >= 160) return;
565 cnt = 160 - WX;
566 tile = WND;
567 dest = BUF + WX;
568
569 while (cnt >= 8)
570 {
571 src = patpix[*(tile++)][WV];
572 blendcpy(dest, src, *(tile++), 8);
573 dest += 8;
574 cnt -= 8;
575 }
576 src = patpix[*(tile++)][WV];
577 blendcpy(dest, src, *(tile++), cnt);
578}
579
580static void spr_enum(void) ICODE_ATTR;
581static void spr_enum(void)
582{
583 int i, j;
584 struct obj *o;
585 struct vissprite ts;
586 int v, pat;
587
588 NS = 0;
589 if (!(R_LCDC & 0x02)) return;
590
591 o = lcd.oam.obj;
592
593 for (i = 40; i; i--, o++)
594 {
595 if (L >= o->y || L + 16 < o->y)
596 continue;
597 if (L + 8 >= o->y && !(R_LCDC & 0x04))
598 continue;
599 VS[NS].x = (int)o->x - 8;
600 v = L - (int)o->y + 16;
601 if (hw.cgb)
602 {
603 pat = o->pat | (((int)o->flags & 0x60) << 5)
604 | (((int)o->flags & 0x08) << 6);
605 VS[NS].pal = 32 + ((o->flags & 0x07) << 2);
606 }
607 else
608 {
609 pat = o->pat | (((int)o->flags & 0x60) << 5);
610 VS[NS].pal = 32 + ((o->flags & 0x10) >> 2);
611 }
612 VS[NS].pri = (o->flags & 0x80) >> 7;
613 if ((R_LCDC & 0x04))
614 {
615 pat &= ~1;
616 if (v >= 8)
617 {
618 v -= 8;
619 pat++;
620 }
621 if (o->flags & 0x40) pat ^= 1;
622 }
623 VS[NS].buf = patpix[pat][v];
624 if (++NS == 10) break;
625 }
626 if (hw.cgb) return;
627 for (i = 0; i < NS; i++)
628 {
629 for (j = i + 1; j < NS; j++)
630 {
631 if (VS[i].x > VS[j].x)
632 {
633 ts = VS[i];
634 VS[i] = VS[j];
635 VS[j] = ts;
636 }
637 }
638 }
639}
640
641static void spr_scan(void) ICODE_ATTR;
642static void spr_scan(void)
643{
644 int i, x;
645 byte pal, b, ns = NS;
646 byte *src, *dest, *bg, *pri;
647 struct vissprite *vs;
648 static byte bgdup[256];
649
650 if (!ns) return;
651
652 memcpy(bgdup, BUF, 256);
653 vs = &VS[ns-1];
654
655 for (; ns; ns--, vs--)
656 {
657 x = vs->x;
658 if (x > 159) continue;
659 if (x < -7) continue;
660 if (x < 0)
661 {
662 src = vs->buf - x;
663 dest = BUF;
664 i = 8 + x;
665 }
666 else
667 {
668 src = vs->buf;
669 dest = BUF + x;
670 if (x > 152) i = 160 - x;
671 else i = 8;
672 }
673 pal = vs->pal;
674 if (vs->pri)
675 {
676 bg = bgdup + (dest - BUF);
677 while (i--)
678 {
679 b = src[i];
680 if (b && !(bg[i]&3)) dest[i] = pal|b;
681 }
682 }
683 else if (hw.cgb)
684 {
685 bg = bgdup + (dest - BUF);
686 pri = PRI + (dest - BUF);
687 while (i--)
688 {
689 b = src[i];
690 if (b && (!pri[i] || !(bg[i]&3)))
691 dest[i] = pal|b;
692 }
693 }
694 else while (i--) if (src[i]) dest[i] = pal|src[i];
695 }
696}
697
698/* Scaling defines */
699#define DX ((LCD_WIDTH<<16) / 160)
700#define DXI ((160<<16) / LCD_WIDTH)
701#define DY ((LCD_HEIGHT<<16) / 144)
702#define DYI ((144<<16) / LCD_HEIGHT)
703
704#define DXR ((LCD_WIDTH<<16) / 144)
705#define DXIR ((144<<16) / LCD_WIDTH)
706#define DYR ((LCD_HEIGHT<<16) / 160)
707#define DYIR ((160<<16) / LCD_HEIGHT)
708
709/* Defines for scale offsets:
710 * S2 is for scaled
711 * S3 if scaled and maintain ratio
712 * S1 is unscaled
713 * R's are the rotated defines
714 */
715#if (LCD_WIDTH>=160) && (LCD_HEIGHT>=144)
716#define S1 ((LCD_HEIGHT-144)/2)*LCD_WIDTH + ((LCD_WIDTH-160)/2)
717#define S2 0
718#define S1R ((LCD_HEIGHT-160)/2)*LCD_WIDTH + ((LCD_WIDTH-144)/2)+144
719#define S2R (LCD_WIDTH-1)
720
721#elif (LCD_WIDTH>=160) && (LCD_HEIGHT<=144)
722#define S1 0
723#define S2 0
724#define S1R LCD_WIDTH-1
725#define S2R LCD_WIDTH-1
726
727#elif (LCD_WIDTH<=160) && (LCD_HEIGHT>=144)
728#define S1 ((LCD_HEIGHT-144)/2)*LCD_WIDTH
729#define S2 ((LCD_HEIGHT-144)/2)*LCD_WIDTH
730#define S1R LCD_WIDTH-1
731#define S2R LCD_WIDTH-1
732
733#else
734#define S1 0
735#define S2 0
736#define S1R LCD_WIDTH-1
737#define S2R LCD_WIDTH-1
738#endif
739
740#if (LCD_WIDTH>LCD_HEIGHT)
741#define S3 ((LCD_WIDTH-((160*DY)>>16))/2)
742#define S3R LCD_WIDTH-1
743#else
744#define S3 ((LCD_HEIGHT-((144*DX)>>16))/2)*LCD_WIDTH
745#define S3R ((LCD_HEIGHT-((160*DXR)>>16))/2)*LCD_WIDTH+LCD_WIDTH-1
746#endif
747
748void lcd_begin(void)
749{
750 fb_data *lcd_fb = get_framebuffer();
751#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
752 vdest=(unsigned char*)lcd_fb;
753#else
754 vdest=lcd_fb;
755#endif
756
757#ifdef HAVE_LCD_COLOR
758
759 if(options.rotate==1) {
760 if(options.scaling == 0)
761 vdest+=S2R;
762 else if (options.scaling == 1)
763 vdest+=S3R;
764 else
765 vdest+=S1R;
766 } else if(options.rotate==2) {
767 if(options.scaling == 0)
768 vdest+=(LCD_WIDTH*LCD_HEIGHT)-S2R;
769 else if (options.scaling == 1)
770 vdest+=(LCD_WIDTH*LCD_HEIGHT)-S3R;
771 else
772 vdest+=(LCD_WIDTH*LCD_HEIGHT)-S1R-144;
773 } else {
774 if(options.scaling == 0)
775 vdest+=S2;
776 else if (options.scaling == 1)
777 vdest+=S3;
778 else
779 vdest+=S1;
780 }
781#endif
782 WY = R_WY;
783}
784
785#ifdef HAVE_LCD_COLOR
786int SCALEWL IDATA_ATTR=1<<16;
787int SCALEWS IDATA_ATTR=1<<16;
788int SCALEHL IDATA_ATTR=1<<16;
789int SCALEHS IDATA_ATTR=1<<16;
790int swidth IDATA_ATTR=160;
791int sremain IDATA_ATTR=LCD_WIDTH-160;
792#endif
793
794void setvidmode(void)
795{
796
797#ifdef HAVE_LCD_COLOR
798 switch(options.scaling)
799 {
800 case 0:
801 if(options.rotate)
802 {
803 SCALEWL=DYR;
804 SCALEWS=DYIR;
805 SCALEHL=DXR;
806 SCALEHS=DXIR;
807 }
808 else
809 {
810 SCALEWL=DX;
811 SCALEWS=DXI;
812 SCALEHL=DY;
813 SCALEHS=DYI;
814 }
815 break;
816 case 1: /* Maintain Ratio */
817 if(options.rotate)
818 {
819 if (DYR<DXR)
820 {
821 SCALEWL=DYR;
822 SCALEWS=DYIR;
823 SCALEHL=DYR;
824 SCALEHS=DYIR;
825 }
826 else
827 {
828 SCALEWL=DXR;
829 SCALEWS=DXIR;
830 SCALEHL=DXR;
831 SCALEHS=DXIR;
832 }
833 }
834 else
835 {
836 if (DY<DX)
837 {
838 SCALEWL=DY;
839 SCALEWS=DYI;
840 SCALEHL=DY;
841 SCALEHS=DYI;
842 }
843 else
844 {
845 SCALEWL=DX;
846 SCALEWS=DXI;
847 SCALEHL=DX;
848 SCALEHS=DXI;
849 }
850 }
851 break;
852 default:
853 SCALEWL=1<<16;
854 SCALEWS=1<<16;
855 SCALEHL=1<<16;
856 SCALEHS=1<<16;
857 }
858 swidth=((160*SCALEWL)>>16);
859
860 if(options.rotate==1) {
861 sremain=-(((160*SCALEWL)>>16)*LCD_WIDTH+1);
862 } else if(options.rotate==2) {
863 sremain=(((160*SCALEWL)>>16)*LCD_WIDTH+1);
864 } else {
865 sremain=LCD_WIDTH-swidth;
866 }
867#endif
868}
869
870void lcd_refreshline(void)
871{
872 if (!(R_LCDC & 0x80))
873 return; /* should not happen... */
874
875#if (LCD_HEIGHT <= 128) && !defined(HAVE_LCD_COLOR)
876 if ( (fb.mode==0&&(R_LY >= 128)) ||
877 (fb.mode==1&&(R_LY < 16)) ||
878 (fb.mode==2&&(R_LY<8||R_LY>=136)) ||
879 (fb.mode==3&&((R_LY%9)==8))
880
881#if LCD_HEIGHT == 64
882 || (R_LY & 1) /* calculate only even lines */
883#endif
884 )
885 return;
886#endif
887
888#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
889 fb_data *lcd_fb = get_framebuffer();
890#endif
891 updatepatpix();
892
893 L = R_LY;
894 X = R_SCX;
895 Y = (R_SCY + L) & 0xff;
896 S = X >> 3;
897 T = Y >> 3;
898 U = X & 7;
899 V = Y & 7;
900
901 WX = R_WX - 7;
902 if (WY>L || WY<0 || WY>143 || WX<-7 || WX>159 || !(R_LCDC&0x20))
903 WX = 160;
904 WT = (L - WY) >> 3;
905 WV = (L - WY) & 7;
906
907 spr_enum();
908
909 tilebuf();
910 if (hw.cgb)
911 {
912 bg_scan_color();
913 wnd_scan_color();
914 if (NS)
915 {
916 bg_scan_pri();
917 wnd_scan_pri();
918 }
919 }
920 else
921 {
922
923 bg_scan();
924 wnd_scan();
925 }
926 spr_scan();
927
928#if !defined(HAVE_LCD_COLOR)
929#if LCD_DEPTH == 1
930 if (scanline_ind == 7)
931#elif LCD_DEPTH == 2
932 if (scanline_ind == 3)
933#endif
934 {
935 if(fb.mode!=3)
936 vid_update(L);
937 else
938 vid_update(L-((int)(L/9)));
939#else
940 {
941 /* Universal Scaling pulled from PrBoom and modified for rockboy */
942
943 static int hpt IDATA_ATTR=0x8000;
944
945 while((hpt>>16)<L+1)
946 {
947 hpt+=SCALEHS;
948 register unsigned int srcpt=0x8000;
949 register unsigned int wcount=swidth;
950 while(wcount--)
951 {
952#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
953 *vdest = BUF[srcpt>>16];
954#else
955 *vdest = PAL[BUF[srcpt>>16]];
956#endif
957 if (options.rotate == 1) {
958 vdest+=LCD_WIDTH;
959 } else if (options.rotate == 2) {
960 vdest-=LCD_WIDTH;
961 } else {
962 vdest++;
963 }
964
965 srcpt+=SCALEWS;
966 }
967 vdest+=sremain;
968 }
969
970 if(L==143)
971 {
972 if(options.showstats)
973 {
974 if(options.showstats==1) {
975 rb->lcd_putsxyf(0,LCD_HEIGHT-10," %d %d ",
976 options.fps, options.frameskip);
977 } else {
978 rb->lcd_putsxyf(0,LCD_HEIGHT-10," FPS: %d Frameskip: %d ",
979 options.fps, options.frameskip);
980 }
981 rb->lcd_update_rect(0,LCD_HEIGHT-10, LCD_WIDTH, 10);
982 }
983
984 hpt=0x8000;
985
986#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
987 if(options.scaling==3) {
988 rb->lcd_blit_pal256((unsigned char*)lcd_fb,(LCD_WIDTH-160)/2, (LCD_HEIGHT-144)/2, (LCD_WIDTH-160)/2, (LCD_HEIGHT-144)/2, 160, 144);
989 } else {
990 rb->lcd_blit_pal256((unsigned char*)lcd_fb,0,0,0,0,LCD_WIDTH,LCD_HEIGHT);
991 }
992#else
993 if(options.scaling==3) {
994 rb->lcd_update_rect( (LCD_WIDTH-160)/2, (LCD_HEIGHT-144)/2, 160, 144);
995 } else {
996 rb->lcd_update();
997 }
998#endif
999 }
1000
1001#endif
1002 }
1003#if LCD_DEPTH == 1
1004 scanline_ind = (scanline_ind+1) % 8;
1005#elif LCD_DEPTH == 2
1006 scanline_ind = (scanline_ind+1) % 4;
1007#endif
1008}
1009
1010#ifdef HAVE_LCD_COLOR
1011void set_pal(void)
1012{
1013 memcpy(dmg_pal,palettes[options.pal], sizeof(dmg_pal));
1014 pal_dirty();
1015}
1016
1017static void updatepalette(int i)
1018{
1019 int c, r, g, b;
1020 fb_data px;
1021
1022 c = (lcd.pal[i<<1] | ((int)lcd.pal[(i<<1)|1] << 8)) & 0x7FFF;
1023#if LCD_PIXELFORMAT == RGB565 || LCD_PIXELFORMAT == RGB565SWAPPED
1024 /* extract color channels to 5 bit red and blue, and 6 bit green */
1025 r = c & 0x001F;
1026 g = (c & 0x03E0) >> 4;
1027 b = c >> 10;
1028 g |= (g >> 5);
1029 px = FB_RGBPACK_LCD(r, g, b);
1030#else
1031 /* extract color channels and normalize to 8-bit */
1032 r = (c & 0x001F) << 3;
1033 g = (c & 0x03E0) >> 2;
1034 b = c >> 7;
1035 r |= (r >> 5);
1036 g |= (g >> 5);
1037 b |= (b >> 5);
1038 px = FB_RGBPACK(r, g, b);
1039#endif
1040 /* updatepalette might get called, but the pallete does not necessarily
1041 * need to be updated.
1042 */
1043 if(memcmp(&PAL[i], &px, sizeof(fb_data)))
1044 {
1045 PAL[i] = px;
1046#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
1047 rb->lcd_pal256_update_pal(PAL);
1048#endif
1049 }
1050}
1051#endif /* HAVE_LCD_COLOR */
1052
1053void pal_write(int i, byte b)
1054{
1055 if (lcd.pal[i] == b) return;
1056 lcd.pal[i] = b;
1057#ifdef HAVE_LCD_COLOR
1058 updatepalette(i>>1);
1059#endif
1060}
1061
1062void pal_write_dmg(int i, int mapnum, byte d)
1063{
1064 int j;
1065 int *cmap = dmg_pal[mapnum];
1066 int c, r, g, b;
1067
1068 if (hw.cgb) return;
1069
1070 for (j = 0; j < 8; j += 2)
1071 {
1072 c = cmap[(d >> j) & 3];
1073 r = (c & 0xf8) >> 3;
1074 g = (c & 0xf800) >> 6;
1075 b = (c & 0xf80000) >> 9;
1076 c = r|g|b;
1077 /* FIXME - handle directly without faking cgb */
1078 pal_write(i+j, c & 0xff);
1079 pal_write(i+j+1, c >> 8);
1080 }
1081}
1082
1083void vram_write(addr a, byte b)
1084{
1085 lcd.vbank[R_VBK&1][a] = b;
1086 if (a >= 0x1800) return;
1087 patdirty[((R_VBK&1)<<9)+(a>>4)] = 1;
1088 anydirty = 1;
1089 pal_dirty();
1090}
1091
1092void vram_dirty(void)
1093{
1094 anydirty = 1;
1095 memset(patdirty, 1, sizeof patdirty);
1096}
1097
1098void pal_dirty(void)
1099{
1100#ifdef HAVE_LCD_COLOR
1101 int i;
1102#endif
1103 if (!hw.cgb)
1104 {
1105
1106 pal_write_dmg(0, 0, R_BGP);
1107 pal_write_dmg(8, 1, R_BGP);
1108 pal_write_dmg(64, 2, R_OBP0);
1109 pal_write_dmg(72, 3, R_OBP1);
1110 }
1111#ifdef HAVE_LCD_COLOR
1112 for (i = 0; i < 64; i++)
1113 updatepalette(i);
1114#endif
1115}
1116
1117void lcd_reset(void)
1118{
1119 memset(&lcd, 0, sizeof lcd);
1120 lcd_begin();
1121 vram_dirty();
1122}