1 // -*- C++ -*-
2 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
3 // Copyright (C) 1999-2003 Forgotten
4 // Copyright (C) 2004 Forgotten and the VBA development team
5
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2, or(at your option)
9 // any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 #ifndef VBA_GFX_H
21 #define VBA_GFX_H
22
23 #include "GBA.h"
24 #include "Gfx.h"
25 #include "Globals.h"
26
27 #include "Port.h"
28
29 //#define SPRITE_DEBUG
30
31 void gfxDrawTextScreen(u16, u16, u16, u32 *);
32 void gfxDrawRotScreen(u16,
33 u16, u16,
34 u16, u16,
35 u16, u16,
36 u16, u16,
37 int&, int&,
38 int,
39 u32*);
40 void gfxDrawRotScreen16Bit(u16,
41 u16, u16,
42 u16, u16,
43 u16, u16,
44 u16, u16,
45 int&, int&,
46 int,
47 u32*);
48 void gfxDrawRotScreen256(u16,
49 u16, u16,
50 u16, u16,
51 u16, u16,
52 u16, u16,
53 int&, int&,
54 int,
55 u32*);
56 void gfxDrawRotScreen16Bit160(u16,
57 u16, u16,
58 u16, u16,
59 u16, u16,
60 u16, u16,
61 int&, int&,
62 int,
63 u32*);
64 void gfxDrawSprites(u32 *);
65 void gfxIncreaseBrightness(u32 *line, int coeff);
66 void gfxDecreaseBrightness(u32 *line, int coeff);
67 void gfxAlphaBlend(u32 *ta, u32 *tb, int ca, int cb);
68
69 void mode0RenderLine();
70 void mode0RenderLineNoWindow();
71 void mode0RenderLineAll();
72
73 void mode1RenderLine();
74 void mode1RenderLineNoWindow();
75 void mode1RenderLineAll();
76
77 void mode2RenderLine();
78 void mode2RenderLineNoWindow();
79 void mode2RenderLineAll();
80
81 void mode3RenderLine();
82 void mode3RenderLineNoWindow();
83 void mode3RenderLineAll();
84
85 void mode4RenderLine();
86 void mode4RenderLineNoWindow();
87 void mode4RenderLineAll();
88
89 void mode5RenderLine();
90 void mode5RenderLineNoWindow();
91 void mode5RenderLineAll();
92
93 extern int coeff[32];
94 extern u32 line0[240];
95 extern u32 line1[240];
96 extern u32 line2[240];
97 extern u32 line3[240];
98 extern u32 lineOBJ[240];
99 extern u32 lineOBJWin[240];
100 extern u32 lineMix[240];
101 extern bool gfxInWin0[240];
102 extern bool gfxInWin1[240];
103
104 extern int gfxBG2Changed;
105 extern int gfxBG3Changed;
106
107 extern int gfxBG2X;
108 extern int gfxBG2Y;
109 extern int gfxBG2LastX;
110 extern int gfxBG2LastY;
111 extern int gfxBG3X;
112 extern int gfxBG3Y;
113 extern int gfxBG3LastX;
114 extern int gfxBG3LastY;
115 extern int gfxLastVCOUNT;
116
gfxClearArray(u32 * array)117 inline void gfxClearArray(u32 *array)
118 {
119 for(int i = 0; i < 240; i++) {
120 *array++ = 0x80000000;
121 }
122 }
123
gfxDrawTextScreen(u16 control,u16 hofs,u16 vofs,u32 * line)124 inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
125 u32 *line)
126 {
127 u16 *palette = (u16 *)paletteRAM;
128 u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
129 u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800];
130 u32 prio = ((control & 3)<<25) + 0x1000000;
131 int sizeX = 256;
132 int sizeY = 256;
133 switch((control >> 14) & 3) {
134 case 0:
135 break;
136 case 1:
137 sizeX = 512;
138 break;
139 case 2:
140 sizeY = 512;
141 break;
142 case 3:
143 sizeX = 512;
144 sizeY = 512;
145 break;
146 }
147
148 int maskX = sizeX-1;
149 int maskY = sizeY-1;
150
151 bool mosaicOn = (control & 0x40) ? true : false;
152
153 int xxx = hofs & maskX;
154 int yyy = (vofs + VCOUNT) & maskY;
155 int mosaicX = (MOSAIC & 0x000F)+1;
156 int mosaicY = ((MOSAIC & 0x00F0)>>4)+1;
157
158 if(mosaicOn) {
159 if((VCOUNT % mosaicY) != 0) {
160 mosaicY = (VCOUNT / mosaicY) * mosaicY;
161 yyy = (vofs + mosaicY) & maskY;
162 }
163 }
164
165 if(yyy > 255 && sizeY > 256) {
166 yyy &= 255;
167 screenBase += 0x400;
168 if(sizeX > 256)
169 screenBase += 0x400;
170 }
171
172 int yshift = ((yyy>>3)<<5);
173 if((control) & 0x80) {
174 u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift;
175 for(int x = 0; x < 240; x++) {
176 u16 data = READ16LE(screenSource);
177
178 int tile = data & 0x3FF;
179 int tileX = (xxx & 7);
180 int tileY = yyy & 7;
181
182 if(data & 0x0400)
183 tileX = 7 - tileX;
184 if(data & 0x0800)
185 tileY = 7 - tileY;
186
187 u8 color = charBase[tile * 64 + tileY * 8 + tileX];
188
189 line[x] = color ? (READ16LE(&palette[color]) | prio): 0x80000000;
190
191 if(data & 0x0400) {
192 if(tileX == 0)
193 screenSource++;
194 } else if(tileX == 7)
195 screenSource++;
196 xxx++;
197 if(xxx == 256) {
198 if(sizeX > 256)
199 screenSource = screenBase + 0x400 + yshift;
200 else {
201 screenSource = screenBase + yshift;
202 xxx = 0;
203 }
204 } else if(xxx >= sizeX) {
205 xxx = 0;
206 screenSource = screenBase + yshift;
207 }
208 }
209 } else {
210 u16 *screenSource = screenBase + 0x400*(xxx>>8)+((xxx&255)>>3) +
211 yshift;
212 for(int x = 0; x < 240; x++) {
213 u16 data = READ16LE(screenSource);
214
215 int tile = data & 0x3FF;
216 int tileX = (xxx & 7);
217 int tileY = yyy & 7;
218
219 if(data & 0x0400)
220 tileX = 7 - tileX;
221 if(data & 0x0800)
222 tileY = 7 - tileY;
223
224 u8 color = charBase[(tile<<5) + (tileY<<2) + (tileX>>1)];
225
226 if(tileX & 1) {
227 color = (color >> 4);
228 } else {
229 color &= 0x0F;
230 }
231
232 int pal = (READ16LE(screenSource)>>8) & 0xF0;
233 line[x] = color ? (READ16LE(&palette[pal + color])|prio): 0x80000000;
234
235 if(data & 0x0400) {
236 if(tileX == 0)
237 screenSource++;
238 } else if(tileX == 7)
239 screenSource++;
240 xxx++;
241 if(xxx == 256) {
242 if(sizeX > 256)
243 screenSource = screenBase + 0x400 + yshift;
244 else {
245 screenSource = screenBase + yshift;
246 xxx = 0;
247 }
248 } else if(xxx >= sizeX) {
249 xxx = 0;
250 screenSource = screenBase + yshift;
251 }
252 }
253 }
254 if(mosaicOn) {
255 if(mosaicX > 1) {
256 int m = 1;
257 for(int i = 0; i < 239; i++) {
258 line[i+1] = line[i];
259 m++;
260 if(m == mosaicX) {
261 m = 1;
262 i++;
263 }
264 }
265 }
266 }
267 }
268
gfxDrawRotScreen(u16 control,u16 x_l,u16 x_h,u16 y_l,u16 y_h,u16 pa,u16 pb,u16 pc,u16 pd,int & currentX,int & currentY,int changed,u32 * line)269 inline void gfxDrawRotScreen(u16 control,
270 u16 x_l, u16 x_h,
271 u16 y_l, u16 y_h,
272 u16 pa, u16 pb,
273 u16 pc, u16 pd,
274 int& currentX, int& currentY,
275 int changed,
276 u32 *line)
277 {
278 u16 *palette = (u16 *)paletteRAM;
279 u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
280 u8 *screenBase = (u8 *)&vram[((control >> 8) & 0x1f) * 0x800];
281 int prio = ((control & 3) << 25) + 0x1000000;
282
283 int sizeX = 128;
284 int sizeY = 128;
285 switch((control >> 14) & 3) {
286 case 0:
287 break;
288 case 1:
289 sizeX = sizeY = 256;
290 break;
291 case 2:
292 sizeX = sizeY = 512;
293 break;
294 case 3:
295 sizeX = sizeY = 1024;
296 break;
297 }
298
299 int dx = pa & 0x7FFF;
300 if(pa & 0x8000)
301 dx |= 0xFFFF8000;
302 int dmx = pb & 0x7FFF;
303 if(pb & 0x8000)
304 dmx |= 0xFFFF8000;
305 int dy = pc & 0x7FFF;
306 if(pc & 0x8000)
307 dy |= 0xFFFF8000;
308 int dmy = pd & 0x7FFFF;
309 if(pd & 0x8000)
310 dmy |= 0xFFFF8000;
311
312 if(VCOUNT == 0)
313 changed = 3;
314
315 if(changed & 1) {
316 currentX = (x_l) | ((x_h & 0x07FF)<<16);
317 if(x_h & 0x0800)
318 currentX |= 0xF8000000;
319 } else {
320 currentX += dmx;
321 }
322
323 if(changed & 2) {
324 currentY = (y_l) | ((y_h & 0x07FF)<<16);
325 if(y_h & 0x0800)
326 currentY |= 0xF8000000;
327 } else {
328 currentY += dmy;
329 }
330
331 int realX = currentX;
332 int realY = currentY;
333
334 if(control & 0x40) {
335 int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
336 int y = (VCOUNT % mosaicY);
337 realX -= y*dmx;
338 realY -= y*dmy;
339 }
340
341 int xxx = (realX >> 8);
342 int yyy = (realY >> 8);
343
344 if(control & 0x2000) {
345 xxx %= sizeX;
346 yyy %= sizeY;
347 if(xxx < 0)
348 xxx += sizeX;
349 if(yyy < 0)
350 yyy += sizeY;
351 }
352
353 if(control & 0x80) {
354 for(int x = 0; x < 240; x++) {
355 if(xxx < 0 ||
356 yyy < 0 ||
357 xxx >= sizeX ||
358 yyy >= sizeY) {
359 line[x] = 0x80000000;
360 } else {
361 int tile = screenBase[(xxx>>3) + (yyy>>3)*(sizeX>>3)];
362
363 int tileX = (xxx & 7);
364 int tileY = yyy & 7;
365
366 u8 color = charBase[(tile<<6) + (tileY<<3) + tileX];
367
368 line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000;
369 }
370 realX += dx;
371 realY += dy;
372
373 xxx = (realX >> 8);
374 yyy = (realY >> 8);
375
376 if(control & 0x2000) {
377 xxx %= sizeX;
378 yyy %= sizeY;
379 if(xxx < 0)
380 xxx += sizeX;
381 if(yyy < 0)
382 yyy += sizeY;
383 }
384 }
385 } else {
386 for(int x = 0; x < 240; x++) {
387 if(xxx < 0 ||
388 yyy < 0 ||
389 xxx >= sizeX ||
390 yyy >= sizeY) {
391 line[x] = 0x80000000;
392 } else {
393 int tile = screenBase[(xxx>>3) + (yyy>>3)*(sizeX>>3)];
394
395 int tileX = (xxx & 7);
396 int tileY = yyy & 7;
397
398 u8 color = charBase[(tile<<6) + (tileY<<3) + tileX];
399
400 line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000;
401 }
402 realX += dx;
403 realY += dy;
404
405 xxx = (realX >> 8);
406 yyy = (realY >> 8);
407
408 if(control & 0x2000) {
409 xxx %= sizeX;
410 yyy %= sizeY;
411 if(xxx < 0)
412 xxx += sizeX;
413 if(yyy < 0)
414 yyy += sizeY;
415 }
416 }
417 }
418
419 if(control & 0x40) {
420 int mosaicX = (MOSAIC & 0xF) + 1;
421 if(mosaicX > 1) {
422 int m = 1;
423 for(int i = 0; i < 239; i++) {
424 line[i+1] = line[i];
425 m++;
426 if(m == mosaicX) {
427 m = 1;
428 i++;
429 }
430 }
431 }
432 }
433 }
434
gfxDrawRotScreen16Bit(u16 control,u16 x_l,u16 x_h,u16 y_l,u16 y_h,u16 pa,u16 pb,u16 pc,u16 pd,int & currentX,int & currentY,int changed,u32 * line)435 inline void gfxDrawRotScreen16Bit(u16 control,
436 u16 x_l, u16 x_h,
437 u16 y_l, u16 y_h,
438 u16 pa, u16 pb,
439 u16 pc, u16 pd,
440 int& currentX, int& currentY,
441 int changed,
442 u32 *line)
443 {
444 u16 *screenBase = (u16 *)&vram[0];
445 int prio = ((control & 3) << 25) + 0x1000000;
446 int sizeX = 240;
447 int sizeY = 160;
448
449 int startX = (x_l) | ((x_h & 0x07FF)<<16);
450 if(x_h & 0x0800)
451 startX |= 0xF8000000;
452 int startY = (y_l) | ((y_h & 0x07FF)<<16);
453 if(y_h & 0x0800)
454 startY |= 0xF8000000;
455
456 int dx = pa & 0x7FFF;
457 if(pa & 0x8000)
458 dx |= 0xFFFF8000;
459 int dmx = pb & 0x7FFF;
460 if(pb & 0x8000)
461 dmx |= 0xFFFF8000;
462 int dy = pc & 0x7FFF;
463 if(pc & 0x8000)
464 dy |= 0xFFFF8000;
465 int dmy = pd & 0x7FFFF;
466 if(pd & 0x8000)
467 dmy |= 0xFFFF8000;
468
469 if(VCOUNT == 0)
470 changed = 3;
471
472 if(changed & 1) {
473 currentX = (x_l) | ((x_h & 0x07FF)<<16);
474 if(x_h & 0x0800)
475 currentX |= 0xF8000000;
476 } else
477 currentX += dmx;
478
479 if(changed & 2) {
480 currentY = (y_l) | ((y_h & 0x07FF)<<16);
481 if(y_h & 0x0800)
482 currentY |= 0xF8000000;
483 } else {
484 currentY += dmy;
485 }
486
487 int realX = currentX;
488 int realY = currentY;
489
490 if(control & 0x40) {
491 int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
492 int y = (VCOUNT % mosaicY);
493 realX -= y*dmx;
494 realY -= y*dmy;
495 }
496
497 int xxx = (realX >> 8);
498 int yyy = (realY >> 8);
499
500 for(int x = 0; x < 240; x++) {
501 if(xxx < 0 ||
502 yyy < 0 ||
503 xxx >= sizeX ||
504 yyy >= sizeY) {
505 line[x] = 0x80000000;
506 } else {
507 line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
508 }
509 realX += dx;
510 realY += dy;
511
512 xxx = (realX >> 8);
513 yyy = (realY >> 8);
514 }
515
516 if(control & 0x40) {
517 int mosaicX = (MOSAIC & 0xF) + 1;
518 if(mosaicX > 1) {
519 int m = 1;
520 for(int i = 0; i < 239; i++) {
521 line[i+1] = line[i];
522 m++;
523 if(m == mosaicX) {
524 m = 1;
525 i++;
526 }
527 }
528 }
529 }
530 }
531
gfxDrawRotScreen256(u16 control,u16 x_l,u16 x_h,u16 y_l,u16 y_h,u16 pa,u16 pb,u16 pc,u16 pd,int & currentX,int & currentY,int changed,u32 * line)532 inline void gfxDrawRotScreen256(u16 control,
533 u16 x_l, u16 x_h,
534 u16 y_l, u16 y_h,
535 u16 pa, u16 pb,
536 u16 pc, u16 pd,
537 int ¤tX, int& currentY,
538 int changed,
539 u32 *line)
540 {
541 u16 *palette = (u16 *)paletteRAM;
542 u8 *screenBase = (DISPCNT & 0x0010) ? &vram[0xA000] : &vram[0x0000];
543 int prio = ((control & 3) << 25) + 0x1000000;
544 int sizeX = 240;
545 int sizeY = 160;
546
547 int startX = (x_l) | ((x_h & 0x07FF)<<16);
548 if(x_h & 0x0800)
549 startX |= 0xF8000000;
550 int startY = (y_l) | ((y_h & 0x07FF)<<16);
551 if(y_h & 0x0800)
552 startY |= 0xF8000000;
553
554 int dx = pa & 0x7FFF;
555 if(pa & 0x8000)
556 dx |= 0xFFFF8000;
557 int dmx = pb & 0x7FFF;
558 if(pb & 0x8000)
559 dmx |= 0xFFFF8000;
560 int dy = pc & 0x7FFF;
561 if(pc & 0x8000)
562 dy |= 0xFFFF8000;
563 int dmy = pd & 0x7FFFF;
564 if(pd & 0x8000)
565 dmy |= 0xFFFF8000;
566
567 if(VCOUNT == 0)
568 changed = 3;
569
570 if(changed & 1) {
571 currentX = (x_l) | ((x_h & 0x07FF)<<16);
572 if(x_h & 0x0800)
573 currentX |= 0xF8000000;
574 } else {
575 currentX += dmx;
576 }
577
578 if(changed & 2) {
579 currentY = (y_l) | ((y_h & 0x07FF)<<16);
580 if(y_h & 0x0800)
581 currentY |= 0xF8000000;
582 } else {
583 currentY += dmy;
584 }
585
586 int realX = currentX;
587 int realY = currentY;
588
589 if(control & 0x40) {
590 int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
591 int y = (VCOUNT / mosaicY) * mosaicY;
592 realX = startX + y*dmx;
593 realY = startY + y*dmy;
594 }
595
596 int xxx = (realX >> 8);
597 int yyy = (realY >> 8);
598
599 for(int x = 0; x < 240; x++) {
600 if(xxx < 0 ||
601 yyy < 0 ||
602 xxx >= sizeX ||
603 yyy >= sizeY) {
604 line[x] = 0x80000000;
605 } else {
606 u8 color = screenBase[yyy * 240 + xxx];
607
608 line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000;
609 }
610 realX += dx;
611 realY += dy;
612
613 xxx = (realX >> 8);
614 yyy = (realY >> 8);
615 }
616
617 if(control & 0x40) {
618 int mosaicX = (MOSAIC & 0xF) + 1;
619 if(mosaicX > 1) {
620 int m = 1;
621 for(int i = 0; i < 239; i++) {
622 line[i+1] = line[i];
623 m++;
624 if(m == mosaicX) {
625 m = 1;
626 i++;
627 }
628 }
629 }
630 }
631 }
632
gfxDrawRotScreen16Bit160(u16 control,u16 x_l,u16 x_h,u16 y_l,u16 y_h,u16 pa,u16 pb,u16 pc,u16 pd,int & currentX,int & currentY,int changed,u32 * line)633 inline void gfxDrawRotScreen16Bit160(u16 control,
634 u16 x_l, u16 x_h,
635 u16 y_l, u16 y_h,
636 u16 pa, u16 pb,
637 u16 pc, u16 pd,
638 int& currentX, int& currentY,
639 int changed,
640 u32 *line)
641 {
642 u16 *screenBase = (DISPCNT & 0x0010) ? (u16 *)&vram[0xa000] :
643 (u16 *)&vram[0];
644 int prio = ((control & 3) << 25) + 0x1000000;
645 int sizeX = 160;
646 int sizeY = 128;
647
648 int startX = (x_l) | ((x_h & 0x07FF)<<16);
649 if(x_h & 0x0800)
650 startX |= 0xF8000000;
651 int startY = (y_l) | ((y_h & 0x07FF)<<16);
652 if(y_h & 0x0800)
653 startY |= 0xF8000000;
654
655 int dx = pa & 0x7FFF;
656 if(pa & 0x8000)
657 dx |= 0xFFFF8000;
658 int dmx = pb & 0x7FFF;
659 if(pb & 0x8000)
660 dmx |= 0xFFFF8000;
661 int dy = pc & 0x7FFF;
662 if(pc & 0x8000)
663 dy |= 0xFFFF8000;
664 int dmy = pd & 0x7FFFF;
665 if(pd & 0x8000)
666 dmy |= 0xFFFF8000;
667
668 if(VCOUNT == 0)
669 changed = 3;
670
671 if(changed & 1) {
672 currentX = (x_l) | ((x_h & 0x07FF)<<16);
673 if(x_h & 0x0800)
674 currentX |= 0xF8000000;
675 } else {
676 currentX += dmx;
677 }
678
679 if(changed & 2) {
680 currentY = (y_l) | ((y_h & 0x07FF)<<16);
681 if(y_h & 0x0800)
682 currentY |= 0xF8000000;
683 } else {
684 currentY += dmy;
685 }
686
687 int realX = currentX;
688 int realY = currentY;
689
690 if(control & 0x40) {
691 int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
692 int y = (VCOUNT / mosaicY) * mosaicY;
693 realX = startX + y*dmx;
694 realY = startY + y*dmy;
695 }
696
697 int xxx = (realX >> 8);
698 int yyy = (realY >> 8);
699
700 for(int x = 0; x < 240; x++) {
701 if(xxx < 0 ||
702 yyy < 0 ||
703 xxx >= sizeX ||
704 yyy >= sizeY) {
705 line[x] = 0x80000000;
706 } else {
707 line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
708 }
709 realX += dx;
710 realY += dy;
711
712 xxx = (realX >> 8);
713 yyy = (realY >> 8);
714 }
715
716 if(control & 0x40) {
717 int mosaicX = (MOSAIC & 0xF) + 1;
718 if(mosaicX > 1) {
719 int m = 1;
720 for(int i = 0; i < 239; i++) {
721 line[i+1] = line[i];
722 m++;
723 if(m == mosaicX) {
724 m = 1;
725 i++;
726 }
727 }
728 }
729 }
730 }
731
gfxDrawSprites(u32 * lineOBJ)732 inline void gfxDrawSprites(u32 *lineOBJ)
733 {
734 int m=0;
735 gfxClearArray(lineOBJ);
736 if(layerEnable & 0x1000) {
737 u16 *sprites = (u16 *)oam;
738 u16 *spritePalette = &((u16 *)paletteRAM)[256];
739 int mosaicY = ((MOSAIC & 0xF000)>>12) + 1;
740 int mosaicX = ((MOSAIC & 0xF00)>>8) + 1;
741 for(int x = 0; x < 128 ; x++) {
742 u16 a0 = READ16LE(sprites++);
743 u16 a1 = READ16LE(sprites++);
744 u16 a2 = READ16LE(sprites++);
745 sprites++;
746
747 // ignore OBJ-WIN
748 if((a0 & 0x0c00) == 0x0800)
749 continue;
750
751 int sizeY = 8;
752 int sizeX = 8;
753
754 switch(((a0 >>12) & 0x0c)|(a1>>14)) {
755 case 0:
756 break;
757 case 1:
758 sizeX = sizeY = 16;
759 break;
760 case 2:
761 sizeX = sizeY = 32;
762 break;
763 case 3:
764 sizeX = sizeY = 64;
765 break;
766 case 4:
767 sizeX = 16;
768 break;
769 case 5:
770 sizeX = 32;
771 break;
772 case 6:
773 sizeX = 32;
774 sizeY = 16;
775 break;
776 case 7:
777 sizeX = 64;
778 sizeY = 32;
779 break;
780 case 8:
781 sizeY = 16;
782 break;
783 case 9:
784 sizeY = 32;
785 break;
786 case 10:
787 sizeX = 16;
788 sizeY = 32;
789 break;
790 case 11:
791 sizeX = 32;
792 sizeY = 64;
793 break;
794 default:
795 continue;
796 }
797
798 #ifdef SPRITE_DEBUG
799 int maskX = sizeX-1;
800 int maskY = sizeY-1;
801 #endif
802
803 int sy = (a0 & 255);
804
805 if(sy > 160)
806 sy -= 256;
807
808 if(a0 & 0x0100) {
809 int fieldX = sizeX;
810 int fieldY = sizeY;
811 if(a0 & 0x0200) {
812 fieldX <<= 1;
813 fieldY <<= 1;
814 }
815
816 int t = VCOUNT - sy;
817 if((t >= 0) && (t < fieldY)) {
818 int sx = (a1 & 0x1FF);
819 if((sx < 240) || (((sx + fieldX) & 511) < 240)) {
820 // int t2 = t - (fieldY >> 1);
821 int rot = (a1 >> 9) & 0x1F;
822 u16 *OAM = (u16 *)oam;
823 int dx = READ16LE(&OAM[3 + (rot << 4)]);
824 if(dx & 0x8000)
825 dx |= 0xFFFF8000;
826 int dmx = READ16LE(&OAM[7 + (rot << 4)]);
827 if(dmx & 0x8000)
828 dmx |= 0xFFFF8000;
829 int dy = READ16LE(&OAM[11 + (rot << 4)]);
830 if(dy & 0x8000)
831 dy |= 0xFFFF8000;
832 int dmy = READ16LE(&OAM[15 + (rot << 4)]);
833 if(dmy & 0x8000)
834 dmy |= 0xFFFF8000;
835
836 if(a0 & 0x1000) {
837 t -= (t % mosaicY);
838 }
839
840 int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx
841 + t * dmx;
842 int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy
843 + t * dmy;
844
845 u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
846
847 if(a0 & 0x2000) {
848 int c = (a2 & 0x3FF);
849 if((DISPCNT & 7) > 2 && (c < 512))
850 continue;
851 int inc = 32;
852 if(DISPCNT & 0x40)
853 inc = sizeX >> 2;
854 else
855 c &= 0x3FE;
856 for(int x = 0; x < fieldX; x++) {
857 int xxx = realX >> 8;
858 int yyy = realY >> 8;
859
860 if(xxx < 0 || xxx >= sizeX ||
861 yyy < 0 || yyy >= sizeY ||
862 sx >= 240);
863 else {
864 u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
865 + ((yyy & 7)<<3) + ((xxx >> 3)<<6) +
866 (xxx & 7))&0x7FFF)];
867 if ((color==0) && (((prio >> 25)&3) <
868 ((lineOBJ[sx]>>25)&3))) {
869 lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
870 if((a0 & 0x1000) && m)
871 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
872 } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
873 lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio;
874 if((a0 & 0x1000) && m)
875 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
876 }
877
878 if (a0 & 0x1000) {
879 m++;
880 if (m==mosaicX)
881 m=0;
882 }
883 #ifdef SPRITE_DEBUG
884 if(t == 0 || t == maskY || x == 0 || x == maskX)
885 lineOBJ[sx] = 0x001F;
886 #endif
887 }
888 sx = (sx+1)&511;;
889 realX += dx;
890 realY += dy;
891 }
892 } else {
893 int c = (a2 & 0x3FF);
894 if((DISPCNT & 7) > 2 && (c < 512))
895 continue;
896
897 int inc = 32;
898 if(DISPCNT & 0x40)
899 inc = sizeX >> 3;
900 int palette = (a2 >> 8) & 0xF0;
901 for(int x = 0; x < fieldX; x++) {
902 int xxx = realX >> 8;
903 int yyy = realY >> 8;
904 if(xxx < 0 || xxx >= sizeX ||
905 yyy < 0 || yyy >= sizeY ||
906 sx >= 240);
907 else {
908 u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
909 + ((yyy & 7)<<2) + ((xxx >> 3)<<5) +
910 ((xxx & 7)>>1))&0x7FFF)];
911 if(xxx & 1)
912 color >>= 4;
913 else
914 color &= 0x0F;
915
916 if ((color==0) && (((prio >> 25)&3) <
917 ((lineOBJ[sx]>>25)&3))) {
918 lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
919 if((a0 & 0x1000) && m)
920 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
921 } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
922 lineOBJ[sx] = READ16LE(&spritePalette[palette+color]) | prio;
923 if((a0 & 0x1000) && m)
924 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
925 }
926 }
927 if((a0 & 0x1000) && m) {
928 m++;
929 if (m==mosaicX)
930 m=0;
931 }
932
933 #ifdef SPRITE_DEBUG
934 if(t == 0 || t == maskY || x == 0 || x == maskX)
935 lineOBJ[sx] = 0x001F;
936 #endif
937 sx = (sx+1)&511;;
938 realX += dx;
939 realY += dy;
940
941 }
942 }
943 }
944 }
945 } else {
946 int t = VCOUNT - sy;
947 if((t >= 0) && (t < sizeY)) {
948 int sx = (a1 & 0x1FF);
949 if(((sx < 240)||(((sx+sizeX)&511)<240)) && !(a0 & 0x0200)) {
950 if(a0 & 0x2000) {
951 if(a1 & 0x2000)
952 t = sizeY - t - 1;
953 int c = (a2 & 0x3FF);
954 if((DISPCNT & 7) > 2 && (c < 512))
955 continue;
956
957 int inc = 32;
958 if(DISPCNT & 0x40) {
959 inc = sizeX >> 2;
960 } else {
961 c &= 0x3FE;
962 }
963 int xxx = 0;
964 if(a1 & 0x1000)
965 xxx = sizeX-1;
966
967 if(a0 & 0x1000) {
968 t -= (t % mosaicY);
969 }
970
971 int address = 0x10000 + ((((c+ (t>>3) * inc) << 5)
972 + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7)) & 0x7FFF);
973
974 if(a1 & 0x1000)
975 xxx = 7;
976 u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
977
978 for(int xx = 0; xx < sizeX; xx++) {
979 if(sx < 240) {
980 u8 color = vram[address];
981 if ((color==0) && (((prio >> 25)&3) <
982 ((lineOBJ[sx]>>25)&3))) {
983 lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
984 if((a0 & 0x1000) && m)
985 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
986 } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
987 lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio;
988 if((a0 & 0x1000) && m)
989 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
990 }
991
992 if (a0 & 0x1000) {
993 m++;
994 if (m==mosaicX)
995 m=0;
996 }
997
998 #ifdef SPRITE_DEBUG
999 if(t == 0 || t == maskY || xx == 0 || xx == maskX)
1000 lineOBJ[sx] = 0x001F;
1001 #endif
1002 }
1003
1004 sx = (sx+1) & 511;
1005 if(a1 & 0x1000) {
1006 xxx--;
1007 address--;
1008 if(xxx == -1) {
1009 address -= 56;
1010 xxx = 7;
1011 }
1012 if(address < 0x10000)
1013 address += 0x8000;
1014 } else {
1015 xxx++;
1016 address++;
1017 if(xxx == 8) {
1018 address += 56;
1019 xxx = 0;
1020 }
1021 if(address > 0x17fff)
1022 address -= 0x8000;
1023 }
1024 }
1025 } else {
1026 if(a1 & 0x2000)
1027 t = sizeY - t - 1;
1028 int c = (a2 & 0x3FF);
1029 if((DISPCNT & 7) > 2 && (c < 512))
1030 continue;
1031
1032 int inc = 32;
1033 if(DISPCNT & 0x40) {
1034 inc = sizeX >> 3;
1035 }
1036 int xxx = 0;
1037 if(a1 & 0x1000)
1038 xxx = sizeX - 1;
1039
1040 if(a0 & 0x1000) {
1041 t -= (t % mosaicY);
1042 }
1043
1044 int address = 0x10000 + ((((c + (t>>3) * inc)<<5)
1045 + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7FFF);
1046 u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
1047 int palette = (a2 >> 8) & 0xF0;
1048 if(a1 & 0x1000) {
1049 xxx = 7;
1050 for(int xx = sizeX - 1; xx >= 0; xx--) {
1051 if(sx < 240) {
1052 u8 color = vram[address];
1053 if(xx & 1) {
1054 color = (color >> 4);
1055 } else
1056 color &= 0x0F;
1057
1058 if ((color==0) && (((prio >> 25)&3) <
1059 ((lineOBJ[sx]>>25)&3))) {
1060 lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
1061 if((a0 & 0x1000) && m)
1062 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
1063 } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
1064 lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio;
1065 if((a0 & 0x1000) && m)
1066 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
1067 }
1068 }
1069 if (a0 & 0x1000) {
1070 m++;
1071 if (m==mosaicX)
1072 m=0;
1073 }
1074 #ifdef SPRITE_DEBUG
1075 if(t == 0 || t == maskY || xx == 0 || xx == maskX)
1076 lineOBJ[sx] = 0x001F;
1077 #endif
1078 sx = (sx+1) & 511;
1079 xxx--;
1080 if(!(xx & 1))
1081 address--;
1082 if(xxx == -1) {
1083 xxx = 7;
1084 address -= 28;
1085 }
1086 if(address < 0x10000)
1087 address += 0x8000;
1088 }
1089 } else {
1090 for(int xx = 0; xx < sizeX; xx++) {
1091 if(sx < 240) {
1092 u8 color = vram[address];
1093 if(xx & 1) {
1094 color = (color >> 4);
1095 } else
1096 color &= 0x0F;
1097
1098 if ((color==0) && (((prio >> 25)&3) <
1099 ((lineOBJ[sx]>>25)&3))) {
1100 lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
1101 if((a0 & 0x1000) && m)
1102 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
1103 } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
1104 lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio;
1105 if((a0 & 0x1000) && m)
1106 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
1107
1108 }
1109 }
1110 if (a0 & 0x1000) {
1111 m++;
1112 if (m==mosaicX)
1113 m=0;
1114 }
1115 #ifdef SPRITE_DEBUG
1116 if(t == 0 || t == maskY || xx == 0 || xx == maskX)
1117 lineOBJ[sx] = 0x001F;
1118 #endif
1119 sx = (sx+1) & 511;
1120 xxx++;
1121 if(xx & 1)
1122 address++;
1123 if(xxx == 8) {
1124 address += 28;
1125 xxx = 0;
1126 }
1127 if(address > 0x17fff)
1128 address -= 0x8000;
1129 }
1130 }
1131 }
1132 }
1133 }
1134 }
1135 }
1136 }
1137 }
1138
gfxDrawOBJWin(u32 * lineOBJWin)1139 inline void gfxDrawOBJWin(u32 *lineOBJWin)
1140 {
1141 gfxClearArray(lineOBJWin);
1142 if(layerEnable & 0x8000) {
1143 u16 *sprites = (u16 *)oam;
1144 // u16 *spritePalette = &((u16 *)paletteRAM)[256];
1145 for(int x = 0; x < 128 ; x++) {
1146 u16 a0 = READ16LE(sprites++);
1147 u16 a1 = READ16LE(sprites++);
1148 u16 a2 = READ16LE(sprites++);
1149 sprites++;
1150
1151 // ignore non OBJ-WIN
1152 if((a0 & 0x0c00) != 0x0800)
1153 continue;
1154
1155 int sizeY = 8;
1156 int sizeX = 8;
1157
1158 switch(((a0 >>12) & 0x0c)|(a1>>14)) {
1159 case 0:
1160 break;
1161 case 1:
1162 sizeX = sizeY = 16;
1163 break;
1164 case 2:
1165 sizeX = sizeY = 32;
1166 break;
1167 case 3:
1168 sizeX = sizeY = 64;
1169 break;
1170 case 4:
1171 sizeX = 16;
1172 break;
1173 case 5:
1174 sizeX = 32;
1175 break;
1176 case 6:
1177 sizeX = 32;
1178 sizeY = 16;
1179 break;
1180 case 7:
1181 sizeX = 64;
1182 sizeY = 32;
1183 break;
1184 case 8:
1185 sizeY = 16;
1186 break;
1187 case 9:
1188 sizeY = 32;
1189 break;
1190 case 10:
1191 sizeX = 16;
1192 sizeY = 32;
1193 break;
1194 case 11:
1195 sizeX = 32;
1196 sizeY = 64;
1197 break;
1198 default:
1199 continue;
1200 }
1201
1202 int sy = (a0 & 255);
1203
1204 if(sy > 160)
1205 sy -= 256;
1206
1207 if(a0 & 0x0100) {
1208 int fieldX = sizeX;
1209 int fieldY = sizeY;
1210 if(a0 & 0x0200) {
1211 fieldX <<= 1;
1212 fieldY <<= 1;
1213 }
1214
1215 int t = VCOUNT - sy;
1216 if((t >= 0) && (t < fieldY)) {
1217 int sx = (a1 & 0x1FF);
1218 if((sx < 240) || (((sx + fieldX) & 511) < 240)) {
1219 // int t2 = t - (fieldY >> 1);
1220 int rot = (a1 >> 9) & 0x1F;
1221 u16 *OAM = (u16 *)oam;
1222 int dx = READ16LE(&OAM[3 + (rot << 4)]);
1223 if(dx & 0x8000)
1224 dx |= 0xFFFF8000;
1225 int dmx = READ16LE(&OAM[7 + (rot << 4)]);
1226 if(dmx & 0x8000)
1227 dmx |= 0xFFFF8000;
1228 int dy = READ16LE(&OAM[11 + (rot << 4)]);
1229 if(dy & 0x8000)
1230 dy |= 0xFFFF8000;
1231 int dmy = READ16LE(&OAM[15 + (rot << 4)]);
1232 if(dmy & 0x8000)
1233 dmy |= 0xFFFF8000;
1234
1235 int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx
1236 + t * dmx;
1237 int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy
1238 + t * dmy;
1239
1240 // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
1241
1242 if(a0 & 0x2000) {
1243 int c = (a2 & 0x3FF);
1244 if((DISPCNT & 7) > 2 && (c < 512))
1245 continue;
1246 int inc = 32;
1247 if(DISPCNT & 0x40)
1248 inc = sizeX >> 2;
1249 else
1250 c &= 0x3FE;
1251 for(int x = 0; x < fieldX; x++) {
1252 int xxx = realX >> 8;
1253 int yyy = realY >> 8;
1254
1255 if(xxx < 0 || xxx >= sizeX ||
1256 yyy < 0 || yyy >= sizeY) {
1257 } else {
1258 u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
1259 + ((yyy & 7)<<3) + ((xxx >> 3)<<6) +
1260 (xxx & 7))&0x7fff)];
1261 if(color) {
1262 lineOBJWin[sx] = 1;
1263 }
1264 }
1265 sx = (sx+1)&511;;
1266 realX += dx;
1267 realY += dy;
1268 }
1269 } else {
1270 int c = (a2 & 0x3FF);
1271 if((DISPCNT & 7) > 2 && (c < 512))
1272 continue;
1273
1274 int inc = 32;
1275 if(DISPCNT & 0x40)
1276 inc = sizeX >> 3;
1277 // int palette = (a2 >> 8) & 0xF0;
1278 for(int x = 0; x < fieldX; x++) {
1279 int xxx = realX >> 8;
1280 int yyy = realY >> 8;
1281
1282 // if(x == 0 || x == (sizeX-1) ||
1283 // t == 0 || t == (sizeY-1)) {
1284 // lineOBJ[sx] = 0x001F | prio;
1285 // } else {
1286 if(xxx < 0 || xxx >= sizeX ||
1287 yyy < 0 || yyy >= sizeY){
1288 } else {
1289 u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
1290 + ((yyy & 7)<<2) + ((xxx >> 3)<<5) +
1291 ((xxx & 7)>>1))&0x7fff)];
1292 if(xxx & 1)
1293 color >>= 4;
1294 else
1295 color &= 0x0F;
1296
1297 if(color) {
1298 lineOBJWin[sx] = 1;
1299 }
1300 }
1301 // }
1302 sx = (sx+1)&511;;
1303 realX += dx;
1304 realY += dy;
1305 }
1306 }
1307 }
1308 }
1309 } else {
1310 int t = VCOUNT - sy;
1311 if((t >= 0) && (t < sizeY)) {
1312 int sx = (a1 & 0x1FF);
1313 if(((sx < 240)||(((sx+sizeX)&511)<240)) && !(a0 & 0x0200)) {
1314 if(a0 & 0x2000) {
1315 if(a1 & 0x2000)
1316 t = sizeY - t - 1;
1317 int c = (a2 & 0x3FF);
1318 if((DISPCNT & 7) > 2 && (c < 512))
1319 continue;
1320
1321 int inc = 32;
1322 if(DISPCNT & 0x40) {
1323 inc = sizeX >> 2;
1324 } else {
1325 c &= 0x3FE;
1326 }
1327 int xxx = 0;
1328 if(a1 & 0x1000)
1329 xxx = sizeX-1;
1330 int address = 0x10000 + ((((c+ (t>>3) * inc) << 5)
1331 + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7))&0x7fff);
1332 if(a1 & 0x1000)
1333 xxx = 7;
1334 // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
1335 for(int xx = 0; xx < sizeX; xx++) {
1336 if(sx < 240) {
1337 u8 color = vram[address];
1338 if(color) {
1339 lineOBJWin[sx] = 1;
1340 }
1341 }
1342
1343 sx = (sx+1) & 511;
1344 if(a1 & 0x1000) {
1345 xxx--;
1346 address--;
1347 if(xxx == -1) {
1348 address -= 56;
1349 xxx = 7;
1350 }
1351 if(address < 0x10000)
1352 address += 0x8000;
1353 } else {
1354 xxx++;
1355 address++;
1356 if(xxx == 8) {
1357 address += 56;
1358 xxx = 0;
1359 }
1360 if(address > 0x17fff)
1361 address -= 0x8000;
1362 }
1363 }
1364 } else {
1365 if(a1 & 0x2000)
1366 t = sizeY - t - 1;
1367 int c = (a2 & 0x3FF);
1368 if((DISPCNT & 7) > 2 && (c < 512))
1369 continue;
1370
1371 int inc = 32;
1372 if(DISPCNT & 0x40) {
1373 inc = sizeX >> 3;
1374 }
1375 int xxx = 0;
1376 if(a1 & 0x1000)
1377 xxx = sizeX - 1;
1378 int address = 0x10000 + ((((c + (t>>3) * inc)<<5)
1379 + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7fff);
1380 // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
1381 // int palette = (a2 >> 8) & 0xF0;
1382 if(a1 & 0x1000) {
1383 xxx = 7;
1384 for(int xx = sizeX - 1; xx >= 0; xx--) {
1385 if(sx < 240) {
1386 u8 color = vram[address];
1387 if(xx & 1) {
1388 color = (color >> 4);
1389 } else
1390 color &= 0x0F;
1391
1392 if(color) {
1393 lineOBJWin[sx] = 1;
1394 }
1395 }
1396 sx = (sx+1) & 511;
1397 xxx--;
1398 if(!(xx & 1))
1399 address--;
1400 if(xxx == -1) {
1401 xxx = 7;
1402 address -= 28;
1403 }
1404 if(address < 0x10000)
1405 address += 0x8000;
1406 }
1407 } else {
1408 for(int xx = 0; xx < sizeX; xx++) {
1409 if(sx < 240) {
1410 u8 color = vram[address];
1411 if(xx & 1) {
1412 color = (color >> 4);
1413 } else
1414 color &= 0x0F;
1415
1416 if(color) {
1417 lineOBJWin[sx] = 1;
1418 }
1419 }
1420 sx = (sx+1) & 511;
1421 xxx++;
1422 if(xx & 1)
1423 address++;
1424 if(xxx == 8) {
1425 address += 28;
1426 xxx = 0;
1427 }
1428 if(address > 0x17fff)
1429 address -= 0x8000;
1430 }
1431 }
1432 }
1433 }
1434 }
1435 }
1436 }
1437 }
1438 }
1439
gfxIncreaseBrightness(u32 color,int coeff)1440 inline u32 gfxIncreaseBrightness(u32 color, int coeff)
1441 {
1442 int r = (color & 0x1F);
1443 int g = ((color >> 5) & 0x1F);
1444 int b = ((color >> 10) & 0x1F);
1445
1446 r = r + (((31 - r) * coeff) >> 4);
1447 g = g + (((31 - g) * coeff) >> 4);
1448 b = b + (((31 - b) * coeff) >> 4);
1449 if(r > 31)
1450 r = 31;
1451 if(g > 31)
1452 g = 31;
1453 if(b > 31)
1454 b = 31;
1455 color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
1456 return color;
1457 }
1458
gfxIncreaseBrightness(u32 * line,int coeff)1459 inline void gfxIncreaseBrightness(u32 *line, int coeff)
1460 {
1461 for(int x = 0; x < 240; x++) {
1462 u32 color = *line;
1463 int r = (color & 0x1F);
1464 int g = ((color >> 5) & 0x1F);
1465 int b = ((color >> 10) & 0x1F);
1466
1467 r = r + (((31 - r) * coeff) >> 4);
1468 g = g + (((31 - g) * coeff) >> 4);
1469 b = b + (((31 - b) * coeff) >> 4);
1470 if(r > 31)
1471 r = 31;
1472 if(g > 31)
1473 g = 31;
1474 if(b > 31)
1475 b = 31;
1476 *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
1477 }
1478 }
1479
gfxDecreaseBrightness(u32 color,int coeff)1480 inline u32 gfxDecreaseBrightness(u32 color, int coeff)
1481 {
1482 int r = (color & 0x1F);
1483 int g = ((color >> 5) & 0x1F);
1484 int b = ((color >> 10) & 0x1F);
1485
1486 r = r - ((r * coeff) >> 4);
1487 g = g - ((g * coeff) >> 4);
1488 b = b - ((b * coeff) >> 4);
1489 if(r < 0)
1490 r = 0;
1491 if(g < 0)
1492 g = 0;
1493 if(b < 0)
1494 b = 0;
1495 color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
1496
1497 return color;
1498 }
1499
gfxDecreaseBrightness(u32 * line,int coeff)1500 inline void gfxDecreaseBrightness(u32 *line, int coeff)
1501 {
1502 for(int x = 0; x < 240; x++) {
1503 u32 color = *line;
1504 int r = (color & 0x1F);
1505 int g = ((color >> 5) & 0x1F);
1506 int b = ((color >> 10) & 0x1F);
1507
1508 r = r - ((r * coeff) >> 4);
1509 g = g - ((g * coeff) >> 4);
1510 b = b - ((b * coeff) >> 4);
1511 if(r < 0)
1512 r = 0;
1513 if(g < 0)
1514 g = 0;
1515 if(b < 0)
1516 b = 0;
1517 *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
1518 }
1519 }
1520
gfxAlphaBlend(u32 color,u32 color2,int ca,int cb)1521 inline u32 gfxAlphaBlend(u32 color, u32 color2, int ca, int cb)
1522 {
1523 if(color < 0x80000000) {
1524 int r = (color & 0x1F);
1525 int g = ((color >> 5) & 0x1F);
1526 int b = ((color >> 10) & 0x1F);
1527 int r0 = (color2 & 0x1F);
1528 int g0 = ((color2 >> 5) & 0x1F);
1529 int b0 = ((color2 >> 10) & 0x1F);
1530
1531 r = ((r * ca) >> 4) + ((r0 * cb) >> 4);
1532 g = ((g * ca) >> 4) + ((g0 * cb) >> 4);
1533 b = ((b * ca) >> 4) + ((b0 * cb) >> 4);
1534
1535 if(r > 31)
1536 r = 31;
1537 if(g > 31)
1538 g = 31;
1539 if(b > 31)
1540 b = 31;
1541
1542 return (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
1543 }
1544 return color;
1545 }
1546
gfxAlphaBlend(u32 * ta,u32 * tb,int ca,int cb)1547 inline void gfxAlphaBlend(u32 *ta, u32 *tb, int ca, int cb)
1548 {
1549 for(int x = 0; x < 240; x++) {
1550 u32 color = *ta;
1551 if(color < 0x80000000) {
1552 int r = (color & 0x1F);
1553 int g = ((color >> 5) & 0x1F);
1554 int b = ((color >> 10) & 0x1F);
1555 u32 color2 = (*tb++);
1556 int r0 = (color2 & 0x1F);
1557 int g0 = ((color2 >> 5) & 0x1F);
1558 int b0 = ((color2 >> 10) & 0x1F);
1559
1560 r = ((r * ca) >> 4) + ((r0 * cb) >> 4);
1561 g = ((g * ca) >> 4) + ((g0 * cb) >> 4);
1562 b = ((b * ca) >> 4) + ((b0 * cb) >> 4);
1563
1564 if(r > 31)
1565 r = 31;
1566 if(g > 31)
1567 g = 31;
1568 if(b > 31)
1569 b = 31;
1570
1571 *ta++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
1572 } else {
1573 ta++;
1574 tb++;
1575 }
1576 }
1577 }
1578
1579 #endif // VBA_GFX_H
1580