diff options
Diffstat (limited to 'apps/plugins/rockboy/lcd.c')
-rw-r--r-- | apps/plugins/rockboy/lcd.c | 956 |
1 files changed, 956 insertions, 0 deletions
diff --git a/apps/plugins/rockboy/lcd.c b/apps/plugins/rockboy/lcd.c new file mode 100644 index 0000000000..6351cb93ed --- /dev/null +++ b/apps/plugins/rockboy/lcd.c | |||
@@ -0,0 +1,956 @@ | |||
1 | |||
2 | |||
3 | #include "config.h" | ||
4 | #include "rockmacros.h" | ||
5 | #include "defs.h" | ||
6 | #include "regs.h" | ||
7 | #include "hw.h" | ||
8 | #include "mem.h" | ||
9 | #include "lcd.h" | ||
10 | #include "rc.h" | ||
11 | #include "fb.h" | ||
12 | #include "palette.h" | ||
13 | #ifdef USE_ASM | ||
14 | #include "asm.h" | ||
15 | #endif | ||
16 | |||
17 | struct lcd lcd; | ||
18 | |||
19 | struct scan scan; | ||
20 | |||
21 | #define BG (scan.bg) | ||
22 | #define WND (scan.wnd) | ||
23 | #define BUF (scan.buf[scanline_ind]) | ||
24 | #define PRI (scan.pri) | ||
25 | |||
26 | #define PAL1 (scan.pal1) | ||
27 | #define PAL2 (scan.pal2) | ||
28 | #define PAL4 (scan.pal4) | ||
29 | |||
30 | #define VS (scan.vs) /* vissprites */ | ||
31 | #define NS (scan.ns) | ||
32 | |||
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) | ||
44 | |||
45 | byte patpix[4096][8][8]; | ||
46 | byte patdirty[1024]; | ||
47 | byte anydirty; | ||
48 | |||
49 | // static int scale = 1; | ||
50 | |||
51 | static int rgb332; | ||
52 | |||
53 | static int sprsort = 1; | ||
54 | static int sprdebug; | ||
55 | static int scanline_ind=0; | ||
56 | |||
57 | #define DEF_PAL { 0x98d0e0, 0x68a0b0, 0x60707C, 0x2C3C3C } | ||
58 | |||
59 | static int dmg_pal[4][4] = { DEF_PAL, DEF_PAL, DEF_PAL, DEF_PAL }; | ||
60 | |||
61 | static int usefilter, filterdmg; | ||
62 | static int filter[3][4] = { | ||
63 | { 195, 25, 0, 35 }, | ||
64 | { 25, 170, 25, 35 }, | ||
65 | { 25, 60, 125, 40 } | ||
66 | }; | ||
67 | |||
68 | rcvar_t lcd_exports[] = | ||
69 | { | ||
70 | RCV_BOOL("rgb332", &rgb332), | ||
71 | RCV_VECTOR("dmg_bgp", dmg_pal[0], 4), | ||
72 | RCV_VECTOR("dmg_wndp", dmg_pal[1], 4), | ||
73 | RCV_VECTOR("dmg_obp0", dmg_pal[2], 4), | ||
74 | RCV_VECTOR("dmg_obp1", dmg_pal[3], 4), | ||
75 | RCV_BOOL("sprsort", &sprsort), | ||
76 | RCV_BOOL("sprdebug", &sprdebug), | ||
77 | RCV_BOOL("colorfilter", &usefilter), | ||
78 | RCV_BOOL("filterdmg", &filterdmg), | ||
79 | RCV_VECTOR("red", filter[0], 4), | ||
80 | RCV_VECTOR("green", filter[1], 4), | ||
81 | RCV_VECTOR("blue", filter[2], 4), | ||
82 | RCV_END | ||
83 | }; | ||
84 | |||
85 | static byte *vdest; | ||
86 | |||
87 | #ifdef ALLOW_UNALIGNED_IO /* long long is ok since this is i386-only anyway? */ | ||
88 | #define MEMCPY8(d, s) ((*(long long *)(d)) = (*(long long *)(s))) | ||
89 | #else | ||
90 | #define MEMCPY8(d, s) memcpy((d), (s), 8) | ||
91 | #endif | ||
92 | |||
93 | |||
94 | |||
95 | |||
96 | #ifndef ASM_UPDATEPATPIX | ||
97 | void updatepatpix(void) | ||
98 | { | ||
99 | int i, j; | ||
100 | #if CONFIG_CPU != SH7034 || defined(SIMULATOR) | ||
101 | int k, a, c; | ||
102 | #endif | ||
103 | byte *vram = lcd.vbank[0]; | ||
104 | |||
105 | if (!anydirty) return; | ||
106 | for (i = 0; i < 1024; i++) | ||
107 | { | ||
108 | if (i == 384) i = 512; | ||
109 | if (i == 896) break; | ||
110 | if (!patdirty[i]) continue; | ||
111 | patdirty[i] = 0; | ||
112 | for (j = 0; j < 8; j++) | ||
113 | { | ||
114 | #if CONFIG_CPU == SH7034 && !defined(SIMULATOR) | ||
115 | asm volatile ( | ||
116 | "mov.w @%2,r1 \n" | ||
117 | "swap.b r1,r2 \n" | ||
118 | |||
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,@%0 \n" | ||
125 | "mov.b r0,@(7,%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,@(1,%0) \n" | ||
132 | "mov.b r0,@(6,%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,@(2,%0) \n" | ||
139 | "mov.b r0,@(5,%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,@(3,%0) \n" | ||
146 | "mov.b r0,@(4,%1) \n" | ||
147 | "mov #0,r0 \n" | ||
148 | "shlr r1 \n" | ||
149 | "rotcl r0 \n" | ||
150 | "shlr r2 \n" | ||
151 | "rotcl r0 \n" | ||
152 | "mov.b r0,@(4,%0) \n" | ||
153 | "mov.b r0,@(3,%1) \n" | ||
154 | "mov #0,r0 \n" | ||
155 | "shlr r1 \n" | ||
156 | "rotcl r0 \n" | ||
157 | "shlr r2 \n" | ||
158 | "rotcl r0 \n" | ||
159 | "mov.b r0,@(5,%0) \n" | ||
160 | "mov.b r0,@(2,%1) \n" | ||
161 | "mov #0,r0 \n" | ||
162 | "shlr r1 \n" | ||
163 | "rotcl r0 \n" | ||
164 | "shlr r2 \n" | ||
165 | "rotcl r0 \n" | ||
166 | "mov.b r0,@(6,%0) \n" | ||
167 | "mov.b r0,@(1,%1) \n" | ||
168 | "mov #0,r0 \n" | ||
169 | "shlr r1 \n" | ||
170 | "rotcl r0 \n" | ||
171 | "shlr r2 \n" | ||
172 | "rotcl r0 \n" | ||
173 | "mov.b r0,@(7,%0) \n" | ||
174 | "mov.b r0,@%1 \n" | ||
175 | : /* outputs */ | ||
176 | : /* inputs */ | ||
177 | /* %0 */ "r"(patpix[i+1024][j]), | ||
178 | /* %1 */ "r"(patpix[i][j]), | ||
179 | /* %2 */ "r"(&vram[(i<<4)|(j<<1)]) | ||
180 | : /* clobbers */ | ||
181 | "r0", "r1", "r2" | ||
182 | ); | ||
183 | #else | ||
184 | a = ((i<<4) | (j<<1)); | ||
185 | for (k = 0; k < 8; k++) | ||
186 | { | ||
187 | c = vram[a] & (1<<k) ? 1 : 0; | ||
188 | c |= vram[a+1] & (1<<k) ? 2 : 0; | ||
189 | patpix[i+1024][j][k] = c; | ||
190 | } | ||
191 | for (k = 0; k < 8; k++) | ||
192 | patpix[i][j][k] = | ||
193 | patpix[i+1024][j][7-k]; | ||
194 | #endif | ||
195 | } | ||
196 | #if CONFIG_CPU == SH7034 && !defined(SIMULATOR) | ||
197 | asm volatile ( | ||
198 | "mov.l @%0,r0 \n" | ||
199 | "mov.l @(4,%0),r1 \n" | ||
200 | "mov.l r0,@(56,%1) \n" | ||
201 | "mov.l r1,@(60,%1) \n" | ||
202 | "mov.l @(8,%0),r0 \n" | ||
203 | "mov.l @(12,%0),r1 \n" | ||
204 | "mov.l r0,@(48,%1) \n" | ||
205 | "mov.l r1,@(52,%1) \n" | ||
206 | "mov.l @(16,%0),r0 \n" | ||
207 | "mov.l @(20,%0),r1 \n" | ||
208 | "mov.l r0,@(40,%1) \n" | ||
209 | "mov.l r1,@(44,%1) \n" | ||
210 | "mov.l @(24,%0),r0 \n" | ||
211 | "mov.l @(28,%0),r1 \n" | ||
212 | "mov.l r0,@(32,%1) \n" | ||
213 | "mov.l r1,@(36,%1) \n" | ||
214 | "mov.l @(32,%0),r0 \n" | ||
215 | "mov.l @(36,%0),r1 \n" | ||
216 | "mov.l r0,@(24,%1) \n" | ||
217 | "mov.l r1,@(28,%1) \n" | ||
218 | "mov.l @(40,%0),r0 \n" | ||
219 | "mov.l @(44,%0),r1 \n" | ||
220 | "mov.l r0,@(16,%1) \n" | ||
221 | "mov.l r1,@(20,%1) \n" | ||
222 | "mov.l @(48,%0),r0 \n" | ||
223 | "mov.l @(52,%0),r1 \n" | ||
224 | "mov.l r0,@(8,%1) \n" | ||
225 | "mov.l r1,@(12,%1) \n" | ||
226 | "mov.l @(56,%0),r0 \n" | ||
227 | "mov.l @(60,%0),r1 \n" | ||
228 | "mov.l r0,@%1 \n" | ||
229 | "mov.l r1,@(4,%1) \n" | ||
230 | |||
231 | "add %2,%0 \n" | ||
232 | "add %2,%1 \n" | ||
233 | |||
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" | ||
266 | : /* outputs */ | ||
267 | : /* inputs */ | ||
268 | /* %0 */ "r"(patpix[i][0]), | ||
269 | /* %1 */ "r"(patpix[i+2048][0]), | ||
270 | /* %2 */ "r"(1024*64) | ||
271 | : /* clobbers */ | ||
272 | "r0", "r1" | ||
273 | ); | ||
274 | #else | ||
275 | for (j = 0; j < 8; j++) | ||
276 | { | ||
277 | for (k = 0; k < 8; k++) | ||
278 | { | ||
279 | patpix[i+2048][j][k] = | ||
280 | patpix[i][7-j][k]; | ||
281 | patpix[i+3072][j][k] = | ||
282 | patpix[i+1024][7-j][k]; | ||
283 | } | ||
284 | } | ||
285 | #endif | ||
286 | } | ||
287 | anydirty = 0; | ||
288 | } | ||
289 | #endif /* ASM_UPDATEPATPIX */ | ||
290 | |||
291 | |||
292 | |||
293 | void tilebuf(void) | ||
294 | { | ||
295 | int i, cnt; | ||
296 | int base; | ||
297 | byte *tilemap, *attrmap; | ||
298 | int *tilebuf; | ||
299 | int *wrap; | ||
300 | static int wraptable[64] = | ||
301 | { | ||
302 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, | ||
303 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,-32 | ||
304 | }; | ||
305 | |||
306 | base = ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5) + S; | ||
307 | tilemap = lcd.vbank[0] + base; | ||
308 | attrmap = lcd.vbank[1] + base; | ||
309 | tilebuf = BG; | ||
310 | wrap = wraptable + S; | ||
311 | cnt = ((WX + 7) >> 3) + 1; | ||
312 | |||
313 | if (hw.cgb) { | ||
314 | if (R_LCDC & 0x10) | ||
315 | for (i = cnt; i > 0; i--) | ||
316 | { | ||
317 | *(tilebuf++) = *tilemap | ||
318 | | (((int)*attrmap & 0x08) << 6) | ||
319 | | (((int)*attrmap & 0x60) << 5); | ||
320 | *(tilebuf++) = (((int)*attrmap & 0x07) << 2); | ||
321 | attrmap += *wrap + 1; | ||
322 | tilemap += *(wrap++) + 1; | ||
323 | } | ||
324 | else | ||
325 | for (i = cnt; i > 0; i--) | ||
326 | { | ||
327 | *(tilebuf++) = (256 + ((n8)*tilemap)) | ||
328 | | (((int)*attrmap & 0x08) << 6) | ||
329 | | (((int)*attrmap & 0x60) << 5); | ||
330 | *(tilebuf++) = (((int)*attrmap & 0x07) << 2); | ||
331 | attrmap += *wrap + 1; | ||
332 | tilemap += *(wrap++) + 1; | ||
333 | } | ||
334 | } | ||
335 | else | ||
336 | { | ||
337 | if (R_LCDC & 0x10) | ||
338 | for (i = cnt; i > 0; i--) | ||
339 | { | ||
340 | *(tilebuf++) = *(tilemap++); | ||
341 | tilemap += *(wrap++); | ||
342 | } | ||
343 | else | ||
344 | for (i = cnt; i > 0; i--) | ||
345 | { | ||
346 | *(tilebuf++) = (256 + ((n8)*(tilemap++))); | ||
347 | tilemap += *(wrap++); | ||
348 | } | ||
349 | } | ||
350 | |||
351 | if (WX >= 160) return; | ||
352 | |||
353 | base = ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5); | ||
354 | tilemap = lcd.vbank[0] + base; | ||
355 | attrmap = lcd.vbank[1] + base; | ||
356 | tilebuf = WND; | ||
357 | cnt = ((160 - WX) >> 3) + 1; | ||
358 | |||
359 | if (hw.cgb) | ||
360 | { | ||
361 | if (R_LCDC & 0x10) | ||
362 | for (i = cnt; i > 0; i--) | ||
363 | { | ||
364 | *(tilebuf++) = *(tilemap++) | ||
365 | | (((int)*attrmap & 0x08) << 6) | ||
366 | | (((int)*attrmap & 0x60) << 5); | ||
367 | *(tilebuf++) = (((int)*(attrmap++)&7) << 2); | ||
368 | } | ||
369 | else | ||
370 | for (i = cnt; i > 0; i--) | ||
371 | { | ||
372 | *(tilebuf++) = (256 + ((n8)*(tilemap++))) | ||
373 | | (((int)*attrmap & 0x08) << 6) | ||
374 | | (((int)*attrmap & 0x60) << 5); | ||
375 | *(tilebuf++) = (((int)*(attrmap++)&7) << 2); | ||
376 | } | ||
377 | } | ||
378 | else | ||
379 | |||
380 | { | ||
381 | if (R_LCDC & 0x10) | ||
382 | for (i = cnt; i > 0; i--) | ||
383 | *(tilebuf++) = *(tilemap++); | ||
384 | else | ||
385 | for (i = cnt; i > 0; i--) | ||
386 | *(tilebuf++) = (256 + ((n8)*(tilemap++))); | ||
387 | } | ||
388 | } | ||
389 | |||
390 | |||
391 | // V = vertical line | ||
392 | // WX = WND start (if 0, no need to do anything) -> WY | ||
393 | // U = start...something...thingy... 7 at most | ||
394 | void bg_scan(void) | ||
395 | { | ||
396 | int cnt; | ||
397 | byte *src, *dest; | ||
398 | int *tile; | ||
399 | |||
400 | if (WX <= 0) return; | ||
401 | cnt = WX; | ||
402 | tile = BG; | ||
403 | dest = BUF; | ||
404 | |||
405 | src = patpix[*(tile++)][V] + U; | ||
406 | memcpy(dest, src, 8-U); | ||
407 | dest += 8-U; | ||
408 | cnt -= 8-U; | ||
409 | if (cnt <= 0) return; | ||
410 | while (cnt >= 8) | ||
411 | { | ||
412 | src = patpix[*(tile++)][V]; | ||
413 | MEMCPY8(dest, src); | ||
414 | dest += 8; | ||
415 | cnt -= 8; | ||
416 | } | ||
417 | src = patpix[*tile][V]; | ||
418 | while (cnt--) | ||
419 | *(dest++) = *(src++); | ||
420 | } | ||
421 | |||
422 | void wnd_scan(void) | ||
423 | { | ||
424 | int cnt; | ||
425 | byte *src, *dest; | ||
426 | int *tile; | ||
427 | |||
428 | if (WX >= 160) return; | ||
429 | cnt = 160 - WX; | ||
430 | tile = WND; | ||
431 | dest = BUF + WX; | ||
432 | |||
433 | while (cnt >= 8) | ||
434 | { | ||
435 | src = patpix[*(tile++)][WV]; | ||
436 | MEMCPY8(dest, src); | ||
437 | dest += 8; | ||
438 | cnt -= 8; | ||
439 | } | ||
440 | src = patpix[*tile][WV]; | ||
441 | while (cnt--) | ||
442 | *(dest++) = *(src++); | ||
443 | } | ||
444 | |||
445 | static void blendcpy(byte *dest, byte *src, byte b, int cnt) | ||
446 | { | ||
447 | while (cnt--) *(dest++) = *(src++) | b; | ||
448 | } | ||
449 | |||
450 | static int priused(void *attr) | ||
451 | { | ||
452 | un32 *a = attr; | ||
453 | return (int)((a[0]|a[1]|a[2]|a[3]|a[4]|a[5]|a[6]|a[7])&0x80808080); | ||
454 | } | ||
455 | |||
456 | void bg_scan_pri(void) | ||
457 | { | ||
458 | int cnt, i; | ||
459 | byte *src, *dest; | ||
460 | |||
461 | if (WX <= 0) return; | ||
462 | i = S; | ||
463 | cnt = WX; | ||
464 | dest = PRI; | ||
465 | src = lcd.vbank[1] + ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5); | ||
466 | |||
467 | if (!priused(src)) | ||
468 | { | ||
469 | memset(dest, 0, cnt); | ||
470 | return; | ||
471 | } | ||
472 | |||
473 | memset(dest, src[i++&31]&128, 8-U); | ||
474 | dest += 8-U; | ||
475 | cnt -= 8-U; | ||
476 | if (cnt <= 0) return; | ||
477 | while (cnt >= 8) | ||
478 | { | ||
479 | memset(dest, src[i++&31]&128, 8); | ||
480 | dest += 8; | ||
481 | cnt -= 8; | ||
482 | } | ||
483 | memset(dest, src[i&31]&128, cnt); | ||
484 | } | ||
485 | |||
486 | void wnd_scan_pri(void) | ||
487 | { | ||
488 | int cnt, i; | ||
489 | byte *src, *dest; | ||
490 | |||
491 | if (WX >= 160) return; | ||
492 | i = 0; | ||
493 | cnt = 160 - WX; | ||
494 | dest = PRI + WX; | ||
495 | src = lcd.vbank[1] + ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5); | ||
496 | |||
497 | if (!priused(src)) | ||
498 | { | ||
499 | memset(dest, 0, cnt); | ||
500 | return; | ||
501 | } | ||
502 | |||
503 | while (cnt >= 8) | ||
504 | { | ||
505 | memset(dest, src[i++]&128, 8); | ||
506 | dest += 8; | ||
507 | cnt -= 8; | ||
508 | } | ||
509 | memset(dest, src[i]&128, cnt); | ||
510 | } | ||
511 | |||
512 | void bg_scan_color(void) | ||
513 | { | ||
514 | int cnt; | ||
515 | byte *src, *dest; | ||
516 | int *tile; | ||
517 | |||
518 | if (WX <= 0) return; | ||
519 | cnt = WX; | ||
520 | tile = BG; | ||
521 | dest = BUF; | ||
522 | |||
523 | src = patpix[*(tile++)][V] + U; | ||
524 | blendcpy(dest, src, *(tile++), 8-U); | ||
525 | dest += 8-U; | ||
526 | cnt -= 8-U; | ||
527 | if (cnt <= 0) return; | ||
528 | while (cnt >= 8) | ||
529 | { | ||
530 | src = patpix[*(tile++)][V]; | ||
531 | blendcpy(dest, src, *(tile++), 8); | ||
532 | dest += 8; | ||
533 | cnt -= 8; | ||
534 | } | ||
535 | src = patpix[*(tile++)][V]; | ||
536 | blendcpy(dest, src, *(tile++), cnt); | ||
537 | } | ||
538 | |||
539 | // blend in window source WND target BUF | ||
540 | // WX = starting X in buf where WND starts | ||
541 | // WV = vertical line selected for this scanline | ||
542 | // reverse: | ||
543 | // WY = starting y in buf where WND starts ? | ||
544 | // W?? = horizontal line selected for this scanline | ||
545 | void wnd_scan_color(void) | ||
546 | { | ||
547 | int cnt; | ||
548 | byte *src, *dest; | ||
549 | int *tile; | ||
550 | |||
551 | if (WX >= 160) return; | ||
552 | cnt = 160 - WX; | ||
553 | tile = WND; | ||
554 | dest = BUF + WX; | ||
555 | |||
556 | while (cnt >= 8) | ||
557 | { | ||
558 | src = patpix[*(tile++)][WV]; | ||
559 | blendcpy(dest, src, *(tile++), 8); | ||
560 | dest += 8; | ||
561 | cnt -= 8; | ||
562 | } | ||
563 | src = patpix[*(tile++)][WV]; | ||
564 | blendcpy(dest, src, *(tile++), cnt); | ||
565 | } | ||
566 | |||
567 | static void recolor(byte *buf, byte fill, int cnt) | ||
568 | { | ||
569 | while (cnt--) *(buf++) |= fill; | ||
570 | } | ||
571 | |||
572 | void spr_count(void) | ||
573 | { | ||
574 | int i; | ||
575 | struct obj *o; | ||
576 | |||
577 | NS = 0; | ||
578 | if (!(R_LCDC & 0x02)) return; | ||
579 | |||
580 | o = lcd.oam.obj; | ||
581 | |||
582 | for (i = 40; i; i--, o++) | ||
583 | { | ||
584 | if (L >= o->y || L + 16 < o->y) | ||
585 | continue; | ||
586 | if (L + 8 >= o->y && !(R_LCDC & 0x04)) | ||
587 | continue; | ||
588 | if (++NS == 10) break; | ||
589 | } | ||
590 | } | ||
591 | |||
592 | void spr_enum(void) | ||
593 | { | ||
594 | int i, j; | ||
595 | struct obj *o; | ||
596 | struct vissprite ts[10]; | ||
597 | int v, pat; | ||
598 | int l, x; | ||
599 | |||
600 | NS = 0; | ||
601 | if (!(R_LCDC & 0x02)) return; | ||
602 | |||
603 | o = lcd.oam.obj; | ||
604 | |||
605 | for (i = 40; i; i--, o++) | ||
606 | { | ||
607 | if (L >= o->y || L + 16 < o->y) | ||
608 | continue; | ||
609 | if (L + 8 >= o->y && !(R_LCDC & 0x04)) | ||
610 | continue; | ||
611 | VS[NS].x = (int)o->x - 8; | ||
612 | v = L - (int)o->y + 16; | ||
613 | if (hw.cgb) | ||
614 | { | ||
615 | pat = o->pat | (((int)o->flags & 0x60) << 5) | ||
616 | | (((int)o->flags & 0x08) << 6); | ||
617 | VS[NS].pal = 32 + ((o->flags & 0x07) << 2); | ||
618 | } | ||
619 | else | ||
620 | { | ||
621 | pat = o->pat | (((int)o->flags & 0x60) << 5); | ||
622 | VS[NS].pal = 32 + ((o->flags & 0x10) >> 2); | ||
623 | } | ||
624 | VS[NS].pri = (o->flags & 0x80) >> 7; | ||
625 | if ((R_LCDC & 0x04)) | ||
626 | { | ||
627 | pat &= ~1; | ||
628 | if (v >= 8) | ||
629 | { | ||
630 | v -= 8; | ||
631 | pat++; | ||
632 | } | ||
633 | if (o->flags & 0x40) pat ^= 1; | ||
634 | } | ||
635 | VS[NS].buf = patpix[pat][v]; | ||
636 | if (++NS == 10) break; | ||
637 | } | ||
638 | if (!sprsort||hw.cgb) return; | ||
639 | /* not quite optimal but it finally works! */ | ||
640 | for (i = 0; i < NS; i++) | ||
641 | { | ||
642 | l = 0; | ||
643 | x = VS[0].x; | ||
644 | for (j = 1; j < NS; j++) | ||
645 | { | ||
646 | if (VS[j].x < x) | ||
647 | { | ||
648 | l = j; | ||
649 | x = VS[j].x; | ||
650 | } | ||
651 | } | ||
652 | ts[i] = VS[l]; | ||
653 | VS[l].x = 160; | ||
654 | } | ||
655 | memcpy(VS, ts, sizeof VS); | ||
656 | } | ||
657 | |||
658 | void spr_scan(void) | ||
659 | { | ||
660 | int i, x; | ||
661 | byte pal, b, ns = NS; | ||
662 | byte *src, *dest, *bg, *pri; | ||
663 | struct vissprite *vs; | ||
664 | static byte bgdup[256]; | ||
665 | |||
666 | if (!ns) return; | ||
667 | |||
668 | memcpy(bgdup, BUF, 256); | ||
669 | vs = &VS[ns-1]; | ||
670 | |||
671 | for (; ns; ns--, vs--) | ||
672 | { | ||
673 | x = vs->x; | ||
674 | if (x >= 160) continue; | ||
675 | if (x <= -8) continue; | ||
676 | if (x < 0) | ||
677 | { | ||
678 | src = vs->buf - x; | ||
679 | dest = BUF; | ||
680 | i = 8 + x; | ||
681 | } | ||
682 | else | ||
683 | { | ||
684 | src = vs->buf; | ||
685 | dest = BUF + x; | ||
686 | if (x > 152) i = 160 - x; | ||
687 | else i = 8; | ||
688 | } | ||
689 | pal = vs->pal; | ||
690 | if (vs->pri) | ||
691 | { | ||
692 | bg = bgdup + (dest - BUF); | ||
693 | while (i--) | ||
694 | { | ||
695 | b = src[i]; | ||
696 | if (b && !(bg[i]&3)) dest[i] = pal|b; | ||
697 | } | ||
698 | } | ||
699 | else if (hw.cgb) | ||
700 | { | ||
701 | bg = bgdup + (dest - BUF); | ||
702 | pri = PRI + (dest - BUF); | ||
703 | while (i--) | ||
704 | { | ||
705 | b = src[i]; | ||
706 | if (b && (!pri[i] || !(bg[i]&3))) | ||
707 | dest[i] = pal|b; | ||
708 | } | ||
709 | } | ||
710 | else while (i--) if (src[i]) dest[i] = pal|src[i]; | ||
711 | /* else while (i--) if (src[i]) dest[i] = 31 + ns; */ | ||
712 | } | ||
713 | // if (sprdebug) for (i = 0; i < NS; i++) BUF[i<<1] = 36; | ||
714 | } | ||
715 | |||
716 | |||
717 | |||
718 | |||
719 | |||
720 | |||
721 | void lcd_begin(void) | ||
722 | { | ||
723 | /* if (fb.indexed) | ||
724 | { | ||
725 | if (rgb332) pal_set332(); | ||
726 | else pal_expire(); | ||
727 | } | ||
728 | while (scale * 160 > fb.w || scale * 144 > fb.h) scale--; */ | ||
729 | vdest = fb.ptr + ((fb.w*fb.pelsize)>>1) | ||
730 | - (80*fb.pelsize) | ||
731 | + ((fb.h>>1) - 72) * fb.pitch; | ||
732 | WY = R_WY; | ||
733 | } | ||
734 | |||
735 | void lcd_refreshline(void) | ||
736 | { | ||
737 | if (!fb.enabled) return; | ||
738 | |||
739 | if (!(R_LCDC & 0x80)) | ||
740 | return; /* should not happen... */ | ||
741 | |||
742 | #if LCD_HEIGHT == 64 | ||
743 | if (R_LY >= 128 || R_LY & 1) /* calculate only even lines */ | ||
744 | #else | ||
745 | if (R_LY >= 128) | ||
746 | #endif | ||
747 | return; | ||
748 | |||
749 | updatepatpix(); | ||
750 | |||
751 | L = R_LY; | ||
752 | #if LCD_HEIGHT == 64 | ||
753 | scanline_ind = (L/2) % 8; | ||
754 | #else | ||
755 | scanline_ind = L % 8; | ||
756 | #endif | ||
757 | X = R_SCX; | ||
758 | Y = (R_SCY + L) & 0xff; | ||
759 | S = X >> 3; | ||
760 | T = Y >> 3; | ||
761 | U = X & 7; | ||
762 | V = Y & 7; | ||
763 | |||
764 | WX = R_WX - 7; | ||
765 | if (WY>L || WY<0 || WY>143 || WX<-7 || WX>159 || !(R_LCDC&0x20)) | ||
766 | WX = 160; | ||
767 | WT = (L - WY) >> 3; | ||
768 | WV = (L - WY) & 7; | ||
769 | |||
770 | spr_enum(); | ||
771 | |||
772 | tilebuf(); | ||
773 | if (hw.cgb) | ||
774 | { | ||
775 | bg_scan_color(); | ||
776 | wnd_scan_color(); | ||
777 | if (NS) | ||
778 | { | ||
779 | bg_scan_pri(); | ||
780 | wnd_scan_pri(); | ||
781 | } | ||
782 | } | ||
783 | else | ||
784 | { | ||
785 | |||
786 | bg_scan(); | ||
787 | wnd_scan(); | ||
788 | recolor(BUF+WX, 0x04, 160-WX); | ||
789 | } | ||
790 | spr_scan(); | ||
791 | /* | ||
792 | if (fb.dirty) memset(fb.ptr, 0, fb.pitch * fb.h); | ||
793 | fb.dirty = 0; | ||
794 | if (density > scale) density = scale; | ||
795 | if (scale == 1) density = 1; | ||
796 | dest = vdest; | ||
797 | */ | ||
798 | if (scanline_ind == 7) | ||
799 | vid_update(L); | ||
800 | // vdest += fb.pitch * scale; | ||
801 | } | ||
802 | |||
803 | |||
804 | |||
805 | |||
806 | |||
807 | |||
808 | /* | ||
809 | static void updatepalette(int i) | ||
810 | { | ||
811 | int c, r, g, b, y, u, v, rr, gg; | ||
812 | |||
813 | c = (lcd.pal[i<<1] | ((int)lcd.pal[(i<<1)|1] << 8)) & 0x7FFF; | ||
814 | r = (c & 0x001F) << 3; | ||
815 | g = (c & 0x03E0) >> 2; | ||
816 | b = (c & 0x7C00) >> 7; | ||
817 | r |= (r >> 5); | ||
818 | g |= (g >> 5); | ||
819 | b |= (b >> 5); | ||
820 | |||
821 | if (usefilter && (filterdmg||hw.cgb)) | ||
822 | { | ||
823 | rr = ((r * filter[0][0] + g * filter[0][1] + b * filter[0][2]) >> 8) + filter[0][3]; | ||
824 | gg = ((r * filter[1][0] + g * filter[1][1] + b * filter[1][2]) >> 8) + filter[1][3]; | ||
825 | b = ((r * filter[2][0] + g * filter[2][1] + b * filter[2][2]) >> 8) + filter[2][3]; | ||
826 | r = rr; | ||
827 | g = gg; | ||
828 | } | ||
829 | |||
830 | if (fb.yuv) | ||
831 | { | ||
832 | y = (((r * 263) + (g * 516) + (b * 100)) >> 10) + 16; | ||
833 | u = (((r * 450) - (g * 377) - (b * 73)) >> 10) + 128; | ||
834 | v = (((r * -152) - (g * 298) + (b * 450)) >> 10) + 128; | ||
835 | if (y < 0) y = 0; if (y > 255) y = 255; | ||
836 | if (u < 0) u = 0; if (u > 255) u = 255; | ||
837 | if (v < 0) v = 0; if (v > 255) v = 255; | ||
838 | PAL4[i] = (y<<fb.cc[0].l) | (y<<fb.cc[3].l) | ||
839 | | (u<<fb.cc[1].l) | (v<<fb.cc[2].l); | ||
840 | return; | ||
841 | } | ||
842 | |||
843 | if (fb.indexed) | ||
844 | { | ||
845 | pal_release(PAL1[i]); | ||
846 | c = pal_getcolor(c, r, g, b); | ||
847 | PAL1[i] = c; | ||
848 | PAL2[i] = (c<<8) | c; | ||
849 | PAL4[i] = (c<<24) | (c<<16) | (c<<8) | c; | ||
850 | return; | ||
851 | } | ||
852 | |||
853 | r = (r >> fb.cc[0].r) << fb.cc[0].l; | ||
854 | g = (g >> fb.cc[1].r) << fb.cc[1].l; | ||
855 | b = (b >> fb.cc[2].r) << fb.cc[2].l; | ||
856 | c = r|g|b; | ||
857 | |||
858 | switch (fb.pelsize) | ||
859 | { | ||
860 | case 1: | ||
861 | PAL1[i] = c; | ||
862 | PAL2[i] = (c<<8) | c; | ||
863 | PAL4[i] = (c<<24) | (c<<16) | (c<<8) | c; | ||
864 | break; | ||
865 | case 2: | ||
866 | PAL2[i] = c; | ||
867 | PAL4[i] = (c<<16) | c; | ||
868 | break; | ||
869 | case 3: | ||
870 | case 4: | ||
871 | PAL4[i] = c; | ||
872 | break; | ||
873 | } | ||
874 | }*/ | ||
875 | |||
876 | void pal_write(int i, byte b) | ||
877 | { | ||
878 | if (lcd.pal[i] == b) return; | ||
879 | lcd.pal[i] = b; | ||
880 | // updatepalette(i>>1); | ||
881 | } | ||
882 | |||
883 | void pal_write_dmg(int i, int mapnum, byte d) | ||
884 | { | ||
885 | int j; | ||
886 | int *cmap = dmg_pal[mapnum]; | ||
887 | int c, r, g, b; | ||
888 | |||
889 | if (hw.cgb) return; | ||
890 | |||
891 | /* if (mapnum >= 2) d = 0xe4; */ | ||
892 | for (j = 0; j < 8; j += 2) | ||
893 | { | ||
894 | c = cmap[(d >> j) & 3]; | ||
895 | r = (c & 0xf8) >> 3; | ||
896 | g = (c & 0xf800) >> 6; | ||
897 | b = (c & 0xf80000) >> 9; | ||
898 | c = r|g|b; | ||
899 | /* FIXME - handle directly without faking cgb */ | ||
900 | pal_write(i+j, c & 0xff); | ||
901 | pal_write(i+j+1, c >> 8); | ||
902 | } | ||
903 | } | ||
904 | |||
905 | void vram_write(int a, byte b) | ||
906 | { | ||
907 | lcd.vbank[R_VBK&1][a] = b; | ||
908 | if (a >= 0x1800) return; | ||
909 | patdirty[((R_VBK&1)<<9)+(a>>4)] = 1; | ||
910 | anydirty = 1; | ||
911 | } | ||
912 | |||
913 | void vram_dirty(void) | ||
914 | { | ||
915 | anydirty = 1; | ||
916 | memset(patdirty, 1, sizeof patdirty); | ||
917 | } | ||
918 | |||
919 | void pal_dirty(void) | ||
920 | { | ||
921 | // int i; | ||
922 | if (!hw.cgb) | ||
923 | { | ||
924 | |||
925 | pal_write_dmg(0, 0, R_BGP); | ||
926 | pal_write_dmg(8, 1, R_BGP); | ||
927 | pal_write_dmg(64, 2, R_OBP0); | ||
928 | pal_write_dmg(72, 3, R_OBP1); | ||
929 | } | ||
930 | // for (i = 0; i < 64; i++) | ||
931 | // updatepalette(i); | ||
932 | } | ||
933 | |||
934 | void lcd_reset(void) | ||
935 | { | ||
936 | memset(&lcd, 0, sizeof lcd); | ||
937 | lcd_begin(); | ||
938 | vram_dirty(); | ||
939 | pal_dirty(); | ||
940 | } | ||
941 | |||
942 | |||
943 | |||
944 | |||
945 | |||
946 | |||
947 | |||
948 | |||
949 | |||
950 | |||
951 | |||
952 | |||
953 | |||
954 | |||
955 | |||
956 | |||