#if => #ifdef
[Rockbox.git] / apps / plugins / rockboy / lcd.c
bloba34db2fd3c1a5dd5691880b3610ea40d288c95c8
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 #include "palette-presets.h"
9 #ifdef USE_ASM
10 #include "asm.h"
11 #endif
13 struct lcd lcd;
15 struct scan scan IBSS_ATTR;
17 #define BG (scan.bg)
18 #define WND (scan.wnd)
20 #if LCD_DEPTH ==16
21 #define BUF (scan.buf)
22 #else
23 #define BUF (scan.buf[scanline_ind])
24 #endif
26 #define PRI (scan.pri)
28 #define PAL (scan.pal)
30 #define VS (scan.vs) /* vissprites */
31 #define NS (scan.ns)
33 #define L (scan.l) /* line */
34 #define X (scan.x) /* screen position */
35 #define Y (scan.y)
36 #define S (scan.s) /* tilemap position */
37 #define T (scan.t)
38 #define U (scan.u) /* position within tile */
39 #define V (scan.v)
40 #define WX (scan.wx)
41 #define WY (scan.wy)
42 #define WT (scan.wt)
43 #define WV (scan.wv)
45 byte patpix[4096][8][8]
46 #if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
47 __attribute__ ((aligned(16))) /* to profit from burst mode */
48 #endif
50 byte patdirty[1024];
51 byte anydirty;
53 #if LCD_DEPTH < 16
54 static int scanline_ind=0;
55 #endif
57 static int dmg_pal[4][4];
59 fb_data *vdest;
61 #ifndef ASM_UPDATEPATPIX
62 void updatepatpix(void)
64 int i, j;
65 #if ((CONFIG_CPU != SH7034) && !defined(CPU_COLDFIRE)) || defined(SIMULATOR)
66 int k, a, c;
67 #endif
68 byte *vram = lcd.vbank[0];
70 if (!anydirty) return;
71 for (i = 0; i < 1024; i++)
73 if (i == 384) i = 512;
74 if (i == 896) break;
75 if (!patdirty[i]) continue;
76 patdirty[i] = 0;
77 for (j = 0; j < 8; j++)
79 #if CONFIG_CPU == SH7034 && !defined(SIMULATOR)
80 asm volatile (
81 "mov.w @%2,r1 \n"
82 "swap.b r1,r2 \n"
84 "mov #0,r0 \n"
85 "shlr r1 \n"
86 "rotcl r0 \n"
87 "shlr r2 \n"
88 "rotcl r0 \n"
89 "mov.b r0,@%0 \n"
90 "mov.b r0,@(7,%1) \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,@(1,%0) \n"
97 "mov.b r0,@(6,%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,@(2,%0) \n"
104 "mov.b r0,@(5,%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,@(3,%0) \n"
111 "mov.b r0,@(4,%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,@(4,%0) \n"
118 "mov.b r0,@(3,%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,@(5,%0) \n"
125 "mov.b r0,@(2,%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,@(6,%0) \n"
132 "mov.b r0,@(1,%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,@(7,%0) \n"
139 "mov.b r0,@%1 \n"
140 : /* outputs */
141 : /* inputs */
142 /* %0 */ "r"(patpix[i+1024][j]),
143 /* %1 */ "r"(patpix[i][j]),
144 /* %2 */ "r"(&vram[(i<<4)|(j<<1)])
145 : /* clobbers */
146 "r0", "r1", "r2"
148 #elif defined(CPU_COLDFIRE) && !defined(SIMULATOR)
149 asm volatile (
150 "move.b (%2),%%d2 \n"
151 "move.b (1,%2),%%d1 \n"
153 "addq.l #8,%1 \n"
154 "clr.l %%d0 \n"
155 "lsr.l #1,%%d1 \n"
156 "addx.l %%d0,%%d0 \n"
157 "lsr.l #1,%%d2 \n"
158 "addx.l %%d0,%%d0 \n"
159 "move.b %%d0,-(%1) \n"
160 "lsl.l #6,%%d0 \n"
161 "lsr.l #1,%%d1 \n"
162 "addx.l %%d0,%%d0 \n"
163 "lsr.l #1,%%d2 \n"
164 "addx.l %%d0,%%d0 \n"
165 "move.b %%d0,-(%1) \n"
166 "lsl.l #6,%%d0 \n"
167 "lsr.l #1,%%d1 \n"
168 "addx.l %%d0,%%d0 \n"
169 "lsr.l #1,%%d2 \n"
170 "addx.l %%d0,%%d0 \n"
171 "move.b %%d0,-(%1) \n"
172 "lsl.l #6,%%d0 \n"
173 "lsr.l #1,%%d1 \n"
174 "addx.l %%d0,%%d0 \n"
175 "lsr.l #1,%%d2 \n"
176 "addx.l %%d0,%%d0 \n"
177 "move.l %%d0,(%0) \n"
178 "move.b %%d0,-(%1) \n"
179 "clr.l %%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.b %%d0,-(%1) \n"
185 "lsl.l #6,%%d0 \n"
186 "lsr.l #1,%%d1 \n"
187 "addx.l %%d0,%%d0 \n"
188 "lsr.l #1,%%d2 \n"
189 "addx.l %%d0,%%d0 \n"
190 "move.b %%d0,-(%1) \n"
191 "lsl.l #6,%%d0 \n"
192 "lsr.l #1,%%d1 \n"
193 "addx.l %%d0,%%d0 \n"
194 "lsr.l #1,%%d2 \n"
195 "addx.l %%d0,%%d0 \n"
196 "move.b %%d0,-(%1) \n"
197 "lsl.l #6,%%d0 \n"
198 "lsr.l #1,%%d1 \n"
199 "addx.l %%d0,%%d0 \n"
200 "lsr.l #1,%%d2 \n"
201 "addx.l %%d0,%%d0 \n"
202 "move.l %%d0,(4,%0) \n"
203 "move.b %%d0,-(%1) \n"
204 : /* outputs */
205 : /* inputs */
206 /* %0 */ "a"(patpix[i+1024][j]),
207 /* %1 */ "a"(patpix[i][j]),
208 /* %2 */ "a"(&vram[(i<<4)|(j<<1)])
209 : /* clobbers */
210 "d0", "d1", "d2"
212 #else
213 a = ((i<<4) | (j<<1));
214 for (k = 0; k < 8; k++)
216 c = vram[a] & (1<<k) ? 1 : 0;
217 c |= vram[a+1] & (1<<k) ? 2 : 0;
218 patpix[i+1024][j][k] = c;
220 for (k = 0; k < 8; k++)
221 patpix[i][j][k] =
222 patpix[i+1024][j][7-k];
223 #endif
225 #if CONFIG_CPU == SH7034 && !defined(SIMULATOR)
226 asm volatile (
227 "mov.l @%0,r0 \n"
228 "mov.l @(4,%0),r1 \n"
229 "mov.l r0,@(56,%1) \n"
230 "mov.l r1,@(60,%1) \n"
231 "mov.l @(8,%0),r0 \n"
232 "mov.l @(12,%0),r1 \n"
233 "mov.l r0,@(48,%1) \n"
234 "mov.l r1,@(52,%1) \n"
235 "mov.l @(16,%0),r0 \n"
236 "mov.l @(20,%0),r1 \n"
237 "mov.l r0,@(40,%1) \n"
238 "mov.l r1,@(44,%1) \n"
239 "mov.l @(24,%0),r0 \n"
240 "mov.l @(28,%0),r1 \n"
241 "mov.l r0,@(32,%1) \n"
242 "mov.l r1,@(36,%1) \n"
243 "mov.l @(32,%0),r0 \n"
244 "mov.l @(36,%0),r1 \n"
245 "mov.l r0,@(24,%1) \n"
246 "mov.l r1,@(28,%1) \n"
247 "mov.l @(40,%0),r0 \n"
248 "mov.l @(44,%0),r1 \n"
249 "mov.l r0,@(16,%1) \n"
250 "mov.l r1,@(20,%1) \n"
251 "mov.l @(48,%0),r0 \n"
252 "mov.l @(52,%0),r1 \n"
253 "mov.l r0,@(8,%1) \n"
254 "mov.l r1,@(12,%1) \n"
255 "mov.l @(56,%0),r0 \n"
256 "mov.l @(60,%0),r1 \n"
257 "mov.l r0,@%1 \n"
258 "mov.l r1,@(4,%1) \n"
260 "add %2,%0 \n"
261 "add %2,%1 \n"
263 "mov.l @%0,r0 \n"
264 "mov.l @(4,%0),r1 \n"
265 "mov.l r0,@(56,%1) \n"
266 "mov.l r1,@(60,%1) \n"
267 "mov.l @(8,%0),r0 \n"
268 "mov.l @(12,%0),r1 \n"
269 "mov.l r0,@(48,%1) \n"
270 "mov.l r1,@(52,%1) \n"
271 "mov.l @(16,%0),r0 \n"
272 "mov.l @(20,%0),r1 \n"
273 "mov.l r0,@(40,%1) \n"
274 "mov.l r1,@(44,%1) \n"
275 "mov.l @(24,%0),r0 \n"
276 "mov.l @(28,%0),r1 \n"
277 "mov.l r0,@(32,%1) \n"
278 "mov.l r1,@(36,%1) \n"
279 "mov.l @(32,%0),r0 \n"
280 "mov.l @(36,%0),r1 \n"
281 "mov.l r0,@(24,%1) \n"
282 "mov.l r1,@(28,%1) \n"
283 "mov.l @(40,%0),r0 \n"
284 "mov.l @(44,%0),r1 \n"
285 "mov.l r0,@(16,%1) \n"
286 "mov.l r1,@(20,%1) \n"
287 "mov.l @(48,%0),r0 \n"
288 "mov.l @(52,%0),r1 \n"
289 "mov.l r0,@(8,%1) \n"
290 "mov.l r1,@(12,%1) \n"
291 "mov.l @(56,%0),r0 \n"
292 "mov.l @(60,%0),r1 \n"
293 "mov.l r0,@%1 \n"
294 "mov.l r1,@(4,%1) \n"
295 : /* outputs */
296 : /* inputs */
297 /* %0 */ "r"(patpix[i][0]),
298 /* %1 */ "r"(patpix[i+2048][0]),
299 /* %2 */ "r"(1024*64)
300 : /* clobbers */
301 "r0", "r1"
303 #elif defined(CPU_COLDFIRE) && !defined(SIMULATOR)
304 asm volatile (
305 "movem.l (%0),%%d0-%%d3 \n"
306 "move.l %%d0,%%d4 \n"
307 "move.l %%d1,%%d5 \n"
308 "movem.l %%d2-%%d5,(48,%1) \n"
309 "movem.l (16,%0),%%d0-%%d3 \n"
310 "move.l %%d0,%%d4 \n"
311 "move.l %%d1,%%d5 \n"
312 "movem.l %%d2-%%d5,(32,%1) \n"
313 "movem.l (32,%0),%%d0-%%d3 \n"
314 "move.l %%d0,%%d4 \n"
315 "move.l %%d1,%%d5 \n"
316 "movem.l %%d2-%%d5,(16,%1) \n"
317 "movem.l (48,%0),%%d0-%%d3 \n"
318 "move.l %%d0,%%d4 \n"
319 "move.l %%d1,%%d5 \n"
320 "movem.l %%d2-%%d5,(%1) \n"
322 "move.l %2,%%d0 \n"
323 "add.l %%d0,%0 \n"
324 "add.l %%d0,%1 \n"
326 "movem.l (%0),%%d0-%%d3 \n"
327 "move.l %%d0,%%d4 \n"
328 "move.l %%d1,%%d5 \n"
329 "movem.l %%d2-%%d5,(48,%1) \n"
330 "movem.l (16,%0),%%d0-%%d3 \n"
331 "move.l %%d0,%%d4 \n"
332 "move.l %%d1,%%d5 \n"
333 "movem.l %%d2-%%d5,(32,%1) \n"
334 "movem.l (32,%0),%%d0-%%d3 \n"
335 "move.l %%d0,%%d4 \n"
336 "move.l %%d1,%%d5 \n"
337 "movem.l %%d2-%%d5,(16,%1) \n"
338 "movem.l (48,%0),%%d0-%%d3 \n"
339 "move.l %%d0,%%d4 \n"
340 "move.l %%d1,%%d5 \n"
341 "movem.l %%d2-%%d5,(%1) \n"
342 : /* outputs */
343 : /* inputs */
344 /* %0 */ "a"(patpix[i][0]),
345 /* %1 */ "a"(patpix[i+2048][0]),
346 /* %2 */ "i"(1024*64)
347 : /* clobbers */
348 "d0", "d1", "d2", "d3", "d4", "d5"
350 #else
351 for (j = 0; j < 8; j++)
353 for (k = 0; k < 8; k++)
355 patpix[i+2048][j][k] =
356 patpix[i][7-j][k];
357 patpix[i+3072][j][k] =
358 patpix[i+1024][7-j][k];
361 #endif
363 anydirty = 0;
365 #endif /* ASM_UPDATEPATPIX */
369 void tilebuf(void)
371 int i, cnt;
372 int base;
373 byte *tilemap, *attrmap;
374 int *tilebuf;
375 int *wrap;
376 static int wraptable[64] =
378 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
379 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,-32
382 base = ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5) + S;
383 tilemap = lcd.vbank[0] + base;
384 attrmap = lcd.vbank[1] + base;
385 tilebuf = BG;
386 wrap = wraptable + S;
387 cnt = ((WX + 7) >> 3) + 1;
389 if (hw.cgb) {
390 if (R_LCDC & 0x10)
391 for (i = cnt; i > 0; i--)
393 *(tilebuf++) = *tilemap
394 | (((int)*attrmap & 0x08) << 6)
395 | (((int)*attrmap & 0x60) << 5);
396 *(tilebuf++) = (((int)*attrmap & 0x07) << 2);
397 attrmap += *wrap + 1;
398 tilemap += *(wrap++) + 1;
400 else
401 for (i = cnt; i > 0; i--)
403 *(tilebuf++) = (256 + ((n8)*tilemap))
404 | (((int)*attrmap & 0x08) << 6)
405 | (((int)*attrmap & 0x60) << 5);
406 *(tilebuf++) = (((int)*attrmap & 0x07) << 2);
407 attrmap += *wrap + 1;
408 tilemap += *(wrap++) + 1;
411 else
413 if (R_LCDC & 0x10)
414 for (i = cnt; i > 0; i--)
416 *(tilebuf++) = *(tilemap++);
417 tilemap += *(wrap++);
419 else
420 for (i = cnt; i > 0; i--)
422 *(tilebuf++) = (256 + ((n8)*(tilemap++)));
423 tilemap += *(wrap++);
427 if (WX >= 160) return;
429 base = ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5);
430 tilemap = lcd.vbank[0] + base;
431 attrmap = lcd.vbank[1] + base;
432 tilebuf = WND;
433 cnt = ((160 - WX) >> 3) + 1;
435 if (hw.cgb)
437 if (R_LCDC & 0x10)
438 for (i = cnt; i > 0; i--)
440 *(tilebuf++) = *(tilemap++)
441 | (((int)*attrmap & 0x08) << 6)
442 | (((int)*attrmap & 0x60) << 5);
443 *(tilebuf++) = (((int)*(attrmap++)&7) << 2);
445 else
446 for (i = cnt; i > 0; i--)
448 *(tilebuf++) = (256 + ((n8)*(tilemap++)))
449 | (((int)*attrmap & 0x08) << 6)
450 | (((int)*attrmap & 0x60) << 5);
451 *(tilebuf++) = (((int)*(attrmap++)&7) << 2);
454 else
457 if (R_LCDC & 0x10)
458 for (i = cnt; i > 0; i--)
459 *(tilebuf++) = *(tilemap++);
460 else
461 for (i = cnt; i > 0; i--)
462 *(tilebuf++) = (256 + ((n8)*(tilemap++)));
467 /* V = vertical line
468 * WX = WND start (if 0, no need to do anything) -> WY
469 * U = start...something...thingy... 7 at most
471 void bg_scan(void)
473 int cnt;
474 byte *src, *dest;
475 int *tile;
477 if (WX <= 0) return;
478 cnt = WX;
479 tile = BG;
480 dest = BUF;
482 src = patpix[*(tile++)][V] + U;
483 memcpy(dest, src, 8-U);
484 dest += 8-U;
485 cnt -= 8-U;
486 if (cnt <= 0) return;
487 while (cnt >= 8)
489 #if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
490 asm volatile (
491 "move.l (%1)+,(%0)+ \n"
492 "move.l (%1)+,(%0)+ \n"
493 : /*outputs*/
494 : /*inputs*/
495 /* %0 */ "a" (dest),
496 /* %1 */ "a" (patpix[*(tile++)][V])
497 //: /* clobbers */
499 #else
500 src = patpix[*(tile++)][V];
501 memcpy(dest,src,8);
502 dest += 8;
503 #endif
504 cnt -= 8;
506 src = patpix[*tile][V];
507 while (cnt--)
508 *(dest++) = *(src++);
511 void wnd_scan(void)
513 int cnt;
514 byte *src, *dest;
515 int *tile;
517 if (WX >= 160) return;
518 cnt = 160 - WX;
519 tile = WND;
520 dest = BUF + WX;
522 while (cnt >= 8)
524 #if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
525 asm volatile (
526 "move.l (%1)+,(%0)+ \n"
527 "move.l (%1)+,(%0)+ \n"
528 : /*outputs*/
529 : /*inputs*/
530 /* %0 */ "a" (dest),
531 /* %1 */ "a" (patpix[*(tile++)][WV])
532 //: /* clobbers */
534 #else
535 src = patpix[*(tile++)][WV];
536 memcpy(dest,src,8);
537 dest += 8;
538 #endif
539 cnt -= 8;
541 src = patpix[*tile][WV];
542 while (cnt--)
543 *(dest++) = *(src++);
546 static void blendcpy(byte *dest, byte *src, byte b, int cnt)
548 while (cnt--) *(dest++) = *(src++) | b;
551 static int priused(void *attr)
553 un32 *a = attr;
554 return (int)((a[0]|a[1]|a[2]|a[3]|a[4]|a[5]|a[6]|a[7])&0x80808080);
557 void bg_scan_pri(void)
559 int cnt, i;
560 byte *src, *dest;
562 if (WX <= 0) return;
563 i = S;
564 cnt = WX;
565 dest = PRI;
566 src = lcd.vbank[1] + ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5);
568 if (!priused(src))
570 memset(dest, 0, cnt);
571 return;
574 memset(dest, src[i++&31]&128, 8-U);
575 dest += 8-U;
576 cnt -= 8-U;
577 if (cnt <= 0) return;
578 while (cnt >= 8)
580 memset(dest, src[i++&31]&128, 8);
581 dest += 8;
582 cnt -= 8;
584 memset(dest, src[i&31]&128, cnt);
587 void wnd_scan_pri(void)
589 int cnt, i;
590 byte *src, *dest;
592 if (WX >= 160) return;
593 i = 0;
594 cnt = 160 - WX;
595 dest = PRI + WX;
596 src = lcd.vbank[1] + ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5);
598 if (!priused(src))
600 memset(dest, 0, cnt);
601 return;
604 while (cnt >= 8)
606 memset(dest, src[i++]&128, 8);
607 dest += 8;
608 cnt -= 8;
610 memset(dest, src[i]&128, cnt);
613 void bg_scan_color(void)
615 int cnt;
616 byte *src, *dest;
617 int *tile;
619 if (WX <= 0) return;
620 cnt = WX;
621 tile = BG;
622 dest = BUF;
624 src = patpix[*(tile++)][V] + U;
625 blendcpy(dest, src, *(tile++), 8-U);
626 dest += 8-U;
627 cnt -= 8-U;
628 if (cnt <= 0) return;
629 while (cnt >= 8)
631 src = patpix[*(tile++)][V];
632 #if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
633 asm volatile (
634 "move.l (%2)+,%%d1 \n"
636 "move.b %%d1,%%d2 \n"
638 "move.b (%1)+,%%d0 \n"
639 "or.l %%d2,%%d0 \n"
640 "move.b %%d0,(%0)+ \n"
642 "move.b (%1)+,%%d0 \n"
643 "or.l %%d1,%%d0 \n"
644 "move.b %%d0,(%0)+ \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 %%d2,%%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"
669 : /*outputs*/
670 : /*inputs*/
671 /* %0 */ "a" (dest),
672 /* %1 */ "a" (src),
673 /* %2 */ "a" (tile)
674 : /* clobbers */
675 "d0", "d1", "d2"
677 #else
678 blendcpy(dest, src, *(tile++), 8);
679 dest += 8;
680 #endif
681 cnt -= 8;
683 src = patpix[*(tile++)][V];
684 blendcpy(dest, src, *(tile++), cnt);
687 void wnd_scan_color(void)
689 int cnt;
690 byte *src, *dest;
691 int *tile;
693 if (WX >= 160) return;
694 cnt = 160 - WX;
695 tile = WND;
696 dest = BUF + WX;
698 while (cnt >= 8)
700 src = patpix[*(tile++)][WV];
701 blendcpy(dest, src, *(tile++), 8);
702 dest += 8;
703 cnt -= 8;
705 src = patpix[*(tile++)][WV];
706 blendcpy(dest, src, *(tile++), cnt);
709 static void recolor(byte *buf, byte fill, int cnt)
711 while (cnt--) *(buf++) |= fill;
714 void spr_enum(void)
716 int i, j;
717 struct obj *o;
718 struct vissprite ts;
719 int v, pat;
721 NS = 0;
722 if (!(R_LCDC & 0x02)) return;
724 o = lcd.oam.obj;
726 for (i = 40; i; i--, o++)
728 if (L >= o->y || L + 16 < o->y)
729 continue;
730 if (L + 8 >= o->y && !(R_LCDC & 0x04))
731 continue;
732 VS[NS].x = (int)o->x - 8;
733 v = L - (int)o->y + 16;
734 if (hw.cgb)
736 pat = o->pat | (((int)o->flags & 0x60) << 5)
737 | (((int)o->flags & 0x08) << 6);
738 VS[NS].pal = 32 + ((o->flags & 0x07) << 2);
740 else
742 pat = o->pat | (((int)o->flags & 0x60) << 5);
743 VS[NS].pal = 32 + ((o->flags & 0x10) >> 2);
745 VS[NS].pri = (o->flags & 0x80) >> 7;
746 if ((R_LCDC & 0x04))
748 pat &= ~1;
749 if (v >= 8)
751 v -= 8;
752 pat++;
754 if (o->flags & 0x40) pat ^= 1;
756 VS[NS].buf = patpix[pat][v];
757 if (++NS == 10) break;
759 if (hw.cgb) return;
760 for (i = 0; i < NS; i++)
762 for (j = i + 1; j < NS; j++)
764 if (VS[i].x > VS[j].x)
766 ts = VS[i];
767 VS[i] = VS[j];
768 VS[j] = ts;
774 void spr_scan(void)
776 int i, x;
777 byte pal, b, ns = NS;
778 byte *src, *dest, *bg, *pri;
779 struct vissprite *vs;
780 static byte bgdup[256];
782 if (!ns) return;
784 memcpy(bgdup, BUF, 256);
785 vs = &VS[ns-1];
787 for (; ns; ns--, vs--)
789 x = vs->x;
790 if (x > 159) continue;
791 if (x < -7) continue;
792 if (x < 0)
794 src = vs->buf - x;
795 dest = BUF;
796 i = 8 + x;
798 else
800 src = vs->buf;
801 dest = BUF + x;
802 if (x > 152) i = 160 - x;
803 else i = 8;
805 pal = vs->pal;
806 if (vs->pri)
808 bg = bgdup + (dest - BUF);
809 while (i--)
811 b = src[i];
812 if (b && !(bg[i]&3)) dest[i] = pal|b;
815 else if (hw.cgb)
817 bg = bgdup + (dest - BUF);
818 pri = PRI + (dest - BUF);
819 while (i--)
821 b = src[i];
822 if (b && (!pri[i] || !(bg[i]&3)))
823 dest[i] = pal|b;
826 else while (i--) if (src[i]) dest[i] = pal|src[i];
830 /* Scaling defines */
831 #define DX ((LCD_WIDTH<<16) / 160)
832 #define DXI ((160<<16) / LCD_WIDTH)
833 #define DY ((LCD_HEIGHT<<16) / 144)
834 #define DYI ((144<<16) / LCD_HEIGHT)
836 void lcd_begin(void)
839 #if (LCD_WIDTH>=160) && (LCD_HEIGHT>=144)
840 #define S1 ((LCD_HEIGHT-144)/2)*LCD_WIDTH + ((LCD_WIDTH-160)/2)
841 #define S2 0
843 #elif (LCD_WIDTH>=160) && (LCD_HEIGHT<=144)
844 #define S1 ((LCD_WIDTH-160)/2)
845 #define S2 ((LCD_WIDTH-160)/2)
847 #elif (LCD_WIDTH<=160) && (LCD_HEIGHT>=144)
848 #define S1 ((LCD_HEIGHT-144)/2)*LCD_WIDTH
849 #define S2 ((LCD_HEIGHT-144)/2)*LCD_WIDTH
851 #else
852 #define S1 0
853 #define S2 0
854 #endif
856 #if (LCD_WIDTH>LCD_HEIGHT)
857 #define S3 ((LCD_WIDTH-(160*LCD_HEIGHT/144))/2)
858 #else
859 #define S3 ((LCD_HEIGHT-(144*LCD_WIDTH/160))/2)*LCD_WIDTH
860 #endif
862 set_pal();
864 if(options.fullscreen == 0)
865 vdest=fb.ptr+S1;
866 else if (options.fullscreen == 1)
867 vdest=fb.ptr+S2;
868 else
869 vdest=fb.ptr+S3;
870 WY = R_WY;
873 int SCALEWL IDATA_ATTR=1<<16;
874 int SCALEWS IDATA_ATTR=1<<16;
875 int SCALEHL IDATA_ATTR=1<<16;
876 int SCALEHS IDATA_ATTR=1<<16;
877 int swidth IDATA_ATTR=160;
878 int sremain IDATA_ATTR=LCD_WIDTH-160;
880 void setvidmode(int mode)
882 switch(mode)
884 case 1:
885 #if (LCD_WIDTH>=160) && (LCD_HEIGHT>=144) /* Full screen scale */
886 SCALEWL=DX;
887 SCALEWS=DXI;
888 SCALEHL=DY;
889 SCALEHS=DYI;
890 #elif (LCD_WIDTH>=160) && (LCD_HEIGHT<144) /* scale the height */
891 SCALEWL=1<<16;
892 SCALEWS=1<<16;
893 SCALEHL=DY;
894 SCALEHS=DYI;
895 #elif (LCD_WIDTH<160) && (LCD_HEIGHT>=144) /* scale the width */
896 SCALEWL=DX;
897 SCALEWS=DXI;
898 SCALEHL=1<<16;
899 SCALEHS=1<<16;
900 #else
901 SCALEWL=DX;
902 SCALEWS=DXI;
903 SCALEHL=DY;
904 SCALEHS=DYI;
905 #endif
906 break;
907 case 2: /* Maintain Ratio */
908 if (DY<DX)
910 SCALEWL=DY;
911 SCALEWS=DYI;
912 SCALEHL=DY;
913 SCALEHS=DYI;
915 else
917 SCALEWL=DX;
918 SCALEWS=DXI;
919 SCALEHL=DX;
920 SCALEHS=DXI;
922 break;
923 default:
924 SCALEWL=1<<16;
925 SCALEWS=1<<16;
926 SCALEHL=1<<16;
927 SCALEHS=1<<16;
929 swidth=(160*SCALEWL)>>16;
930 sremain=LCD_WIDTH-swidth;
933 void lcd_refreshline(void)
935 #ifdef HAVE_LCD_COLOR
936 char frameout[30];
937 #endif
939 if (!(R_LCDC & 0x80))
940 return; /* should not happen... */
942 #if (LCD_HEIGHT <= 128) && !defined(HAVE_LCD_COLOR)
943 if ( (fb.mode==0&&(R_LY >= 128)) ||
944 (fb.mode==1&&(R_LY < 16)) ||
945 (fb.mode==2&&(R_LY<8||R_LY>=136)) ||
946 (fb.mode==3&&((R_LY%9)==8))
948 #if LCD_HEIGHT == 64
949 || (R_LY & 1) /* calculate only even lines */
950 #endif
952 return;
953 #endif
955 updatepatpix();
957 L = R_LY;
958 X = R_SCX;
959 Y = (R_SCY + L) & 0xff;
960 S = X >> 3;
961 T = Y >> 3;
962 U = X & 7;
963 V = Y & 7;
965 WX = R_WX - 7;
966 if (WY>L || WY<0 || WY>143 || WX<-7 || WX>159 || !(R_LCDC&0x20))
967 WX = 160;
968 WT = (L - WY) >> 3;
969 WV = (L - WY) & 7;
971 spr_enum();
973 tilebuf();
974 if (hw.cgb)
976 bg_scan_color();
977 wnd_scan_color();
978 if (NS)
980 bg_scan_pri();
981 wnd_scan_pri();
984 else
987 bg_scan();
988 wnd_scan();
989 recolor(BUF+WX, 0x04, 160-WX);
991 spr_scan();
993 #if !defined(HAVE_LCD_COLOR)
994 #if LCD_DEPTH == 1
995 if (scanline_ind == 7)
996 #elif LCD_DEPTH == 2
997 if (scanline_ind == 3)
998 #endif
1000 if(fb.mode!=3)
1001 vid_update(L);
1002 else
1003 vid_update(L-((int)(L/9)));
1004 #else
1006 /* Universal Scaling pulled from PrBoom and modified for rockboy */
1008 static int hpt IDATA_ATTR=0x8000;
1010 while((hpt>>16)<L+1)
1012 hpt+=SCALEHS;
1013 register unsigned int srcpt=0x8000;
1014 register unsigned int wcount=swidth;
1015 register unsigned int remain=sremain;
1016 while(wcount--)
1018 #if LCD_HEIGHT<144 /* cut off the bottom part of the screen that won't fit */
1019 if (options.fullscreen==0 && (hpt>>16)>LCD_HEIGHT)
1020 break;
1021 #endif
1023 #if LCD_WIDTH<160 /* cut off the right part of the screen that won't fit */
1024 if(options.fullscreen==0 && wcount<(160-LCD_WIDTH)) {
1025 vdest+=wcount;
1026 wcount = 0;
1028 #endif
1030 *vdest++ = PAL[BUF[srcpt>>16]];
1031 srcpt+=SCALEWS;
1033 #if LCD_HEIGHT<144
1034 if (options.fullscreen!=0 || (hpt>>16)<(LCD_HEIGHT))
1035 #endif
1036 vdest+=remain;
1039 if(L==143)
1041 if(options.showstats)
1043 snprintf(frameout,sizeof(frameout),"FPS: %d Frameskip: %d ",options.fps, options.frameskip);
1044 rb->lcd_putsxy(0,LCD_HEIGHT-10,frameout);
1047 hpt=0x8000;
1048 rb->lcd_update();
1051 #endif
1053 #if LCD_DEPTH == 1
1054 scanline_ind = (scanline_ind+1) % 8;
1055 #elif LCD_DEPTH == 2
1056 scanline_ind = (scanline_ind+1) % 4;
1057 #endif
1060 void set_pal(void)
1062 memcpy(dmg_pal,palettes[options.pal], sizeof dmg_pal);
1063 pal_dirty();
1066 #ifdef HAVE_LCD_COLOR
1067 static void updatepalette(int i)
1069 int c, r, g, b;
1071 c = (lcd.pal[i<<1] | ((int)lcd.pal[(i<<1)|1] << 8)) & 0x7FFF;
1072 r = (c & 0x001F) << 3;
1073 g = (c & 0x03E0) >> 2;
1074 b = (c & 0x7C00) >> 7;
1075 r |= (r >> 5);
1076 g |= (g >> 5);
1077 b |= (b >> 5);
1079 r = (r >> fb.cc[0].r) << fb.cc[0].l;
1080 g = (g >> fb.cc[1].r) << fb.cc[1].l;
1081 b = (b >> fb.cc[2].r) << fb.cc[2].l;
1083 #if LCD_PIXELFORMAT == RGB565
1084 c = r|g|b;
1085 #elif LCD_PIXELFORMAT == RGB565SWAPPED
1086 c = swap16(r|g|b);
1087 #endif
1088 PAL[i] = c;
1090 #endif
1092 void pal_write(int i, byte b)
1094 if (lcd.pal[i] == b) return;
1095 lcd.pal[i] = b;
1096 #if LCD_DEPTH ==16
1097 updatepalette(i>>1);
1098 #endif
1101 void pal_write_dmg(int i, int mapnum, byte d)
1103 int j;
1104 int *cmap = dmg_pal[mapnum];
1105 int c, r, g, b;
1107 if (hw.cgb) return;
1109 for (j = 0; j < 8; j += 2)
1111 c = cmap[(d >> j) & 3];
1112 r = (c & 0xf8) >> 3;
1113 g = (c & 0xf800) >> 6;
1114 b = (c & 0xf80000) >> 9;
1115 c = r|g|b;
1116 /* FIXME - handle directly without faking cgb */
1117 pal_write(i+j, c & 0xff);
1118 pal_write(i+j+1, c >> 8);
1122 void vram_write(addr a, byte b)
1124 lcd.vbank[R_VBK&1][a] = b;
1125 if (a >= 0x1800) return;
1126 patdirty[((R_VBK&1)<<9)+(a>>4)] = 1;
1127 anydirty = 1;
1130 void vram_dirty(void)
1132 anydirty = 1;
1133 memset(patdirty, 1, sizeof patdirty);
1136 void pal_dirty(void)
1138 #if LCD_DEPTH ==16
1139 int i;
1140 #endif
1141 if (!hw.cgb)
1144 pal_write_dmg(0, 0, R_BGP);
1145 pal_write_dmg(8, 1, R_BGP);
1146 pal_write_dmg(64, 2, R_OBP0);
1147 pal_write_dmg(72, 3, R_OBP1);
1149 #if LCD_DEPTH ==16
1150 for (i = 0; i < 64; i++)
1151 updatepalette(i);
1152 #endif
1155 void lcd_reset(void)
1157 memset(&lcd, 0, sizeof lcd);
1158 lcd_begin();
1159 vram_dirty();