A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1122 lines 27 kB view raw
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}