remove more unportable ASM, obsoleting C_CORE define
[rofl0r-VisualBoyAdvance.git] / src / Gfx.h
blob2de0fd87b847fe386ec501ae810a3245275c9621
1 // -*- C++ -*-
2 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
3 // Copyright (C) 1999-2003 Forgotten
4 // Copyright (C) 2005 Forgotten and the VBA development team
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.
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.
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.
20 #ifndef VBA_GFX_H
21 #define VBA_GFX_H
23 #include "GBA.h"
24 #include "Gfx.h"
25 #include "Globals.h"
27 #include "Port.h"
29 //#define SPRITE_DEBUG
31 static void gfxDrawTextScreen(u16, u16, u16, u32 *);
32 static void gfxDrawRotScreen(u16,
33 u16, u16,
34 u16, u16,
35 u16, u16,
36 u16, u16,
37 int*, int*,
38 int,
39 u32*);
40 static void gfxDrawRotScreen16Bit(u16,
41 u16, u16,
42 u16, u16,
43 u16, u16,
44 u16, u16,
45 int*, int*,
46 int,
47 u32*);
48 static void gfxDrawRotScreen256(u16,
49 u16, u16,
50 u16, u16,
51 u16, u16,
52 u16, u16,
53 int*, int*,
54 int,
55 u32*);
56 static void gfxDrawRotScreen16Bit160(u16,
57 u16, u16,
58 u16, u16,
59 u16, u16,
60 u16, u16,
61 int*, int*,
62 int,
63 u32*);
64 static void gfxDrawSprites(u32 *);
65 static void gfxIncreaseBrightness(u32 *line, int coeff);
66 static void gfxDecreaseBrightness(u32 *line, int coeff);
67 static void gfxAlphaBlend(u32 *ta, u32 *tb, int ca, int cb);
69 void mode0RenderLine();
70 void mode0RenderLineNoWindow();
71 void mode0RenderLineAll();
73 void mode1RenderLine();
74 void mode1RenderLineNoWindow();
75 void mode1RenderLineAll();
77 void mode2RenderLine();
78 void mode2RenderLineNoWindow();
79 void mode2RenderLineAll();
81 void mode3RenderLine();
82 void mode3RenderLineNoWindow();
83 void mode3RenderLineAll();
85 void mode4RenderLine();
86 void mode4RenderLineNoWindow();
87 void mode4RenderLineAll();
89 void mode5RenderLine();
90 void mode5RenderLineNoWindow();
91 void mode5RenderLineAll();
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 extern int lineOBJpixleft[128];
105 extern int gfxBG2Changed;
106 extern int gfxBG3Changed;
108 extern int gfxBG2X;
109 extern int gfxBG2Y;
110 extern int gfxBG2LastX;
111 extern int gfxBG2LastY;
112 extern int gfxBG3X;
113 extern int gfxBG3Y;
114 extern int gfxBG3LastX;
115 extern int gfxBG3LastY;
116 extern int gfxLastVCOUNT;
118 static inline void gfxClearArray(u32 *array)
120 for(int i = 0; i < 240; i++) {
121 *array++ = 0x80000000;
125 static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
126 u32 *line)
128 u16 *palette = (u16 *)paletteRAM;
129 u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
130 u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800];
131 u32 prio = ((control & 3)<<25) + 0x1000000;
132 int sizeX = 256;
133 int sizeY = 256;
134 switch((control >> 14) & 3) {
135 case 0:
136 break;
137 case 1:
138 sizeX = 512;
139 break;
140 case 2:
141 sizeY = 512;
142 break;
143 case 3:
144 sizeX = 512;
145 sizeY = 512;
146 break;
149 int maskX = sizeX-1;
150 int maskY = sizeY-1;
152 bool mosaicOn = (control & 0x40) ? true : false;
154 int xxx = hofs & maskX;
155 int yyy = (vofs + VCOUNT) & maskY;
156 int mosaicX = (MOSAIC & 0x000F)+1;
157 int mosaicY = ((MOSAIC & 0x00F0)>>4)+1;
159 if(mosaicOn) {
160 if((VCOUNT % mosaicY) != 0) {
161 mosaicY = (VCOUNT / mosaicY) * mosaicY;
162 yyy = (vofs + mosaicY) & maskY;
166 if(yyy > 255 && sizeY > 256) {
167 yyy &= 255;
168 screenBase += 0x400;
169 if(sizeX > 256)
170 screenBase += 0x400;
173 int yshift = ((yyy>>3)<<5);
174 if((control) & 0x80) {
175 u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift;
176 for(int x = 0; x < 240; x++) {
177 u16 data = READ16LE(screenSource);
179 int tile = data & 0x3FF;
180 int tileX = (xxx & 7);
181 int tileY = yyy & 7;
183 if(data & 0x0400)
184 tileX = 7 - tileX;
185 if(data & 0x0800)
186 tileY = 7 - tileY;
188 u8 color = charBase[tile * 64 + tileY * 8 + tileX];
190 line[x] = color ? (READ16LE(&palette[color]) | prio): 0x80000000;
192 if(data & 0x0400) {
193 if(tileX == 0)
194 screenSource++;
195 } else if(tileX == 7)
196 screenSource++;
197 xxx++;
198 if(xxx == 256) {
199 if(sizeX > 256)
200 screenSource = screenBase + 0x400 + yshift;
201 else {
202 screenSource = screenBase + yshift;
203 xxx = 0;
205 } else if(xxx >= sizeX) {
206 xxx = 0;
207 screenSource = screenBase + yshift;
210 } else {
211 u16 *screenSource = screenBase + 0x400*(xxx>>8)+((xxx&255)>>3) +
212 yshift;
213 for(int x = 0; x < 240; x++) {
214 u16 data = READ16LE(screenSource);
216 int tile = data & 0x3FF;
217 int tileX = (xxx & 7);
218 int tileY = yyy & 7;
220 if(data & 0x0400)
221 tileX = 7 - tileX;
222 if(data & 0x0800)
223 tileY = 7 - tileY;
225 u8 color = charBase[(tile<<5) + (tileY<<2) + (tileX>>1)];
227 if(tileX & 1) {
228 color = (color >> 4);
229 } else {
230 color &= 0x0F;
233 int pal = (READ16LE(screenSource)>>8) & 0xF0;
234 line[x] = color ? (READ16LE(&palette[pal + color])|prio): 0x80000000;
236 if(data & 0x0400) {
237 if(tileX == 0)
238 screenSource++;
239 } else if(tileX == 7)
240 screenSource++;
241 xxx++;
242 if(xxx == 256) {
243 if(sizeX > 256)
244 screenSource = screenBase + 0x400 + yshift;
245 else {
246 screenSource = screenBase + yshift;
247 xxx = 0;
249 } else if(xxx >= sizeX) {
250 xxx = 0;
251 screenSource = screenBase + yshift;
255 if(mosaicOn) {
256 if(mosaicX > 1) {
257 int m = 1;
258 for(int i = 0; i < 239; i++) {
259 line[i+1] = line[i];
260 m++;
261 if(m == mosaicX) {
262 m = 1;
263 i++;
270 static inline void gfxDrawRotScreen(u16 control,
271 u16 x_l, u16 x_h,
272 u16 y_l, u16 y_h,
273 u16 pa, u16 pb,
274 u16 pc, u16 pd,
275 int *currentX, int *currentY,
276 int changed,
277 u32 *line)
279 u16 *palette = (u16 *)paletteRAM;
280 u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
281 u8 *screenBase = (u8 *)&vram[((control >> 8) & 0x1f) * 0x800];
282 int prio = ((control & 3) << 25) + 0x1000000;
284 int sizeX = 128;
285 int sizeY = 128;
286 switch((control >> 14) & 3) {
287 case 0:
288 break;
289 case 1:
290 sizeX = sizeY = 256;
291 break;
292 case 2:
293 sizeX = sizeY = 512;
294 break;
295 case 3:
296 sizeX = sizeY = 1024;
297 break;
300 int dx = pa & 0x7FFF;
301 if(pa & 0x8000)
302 dx |= 0xFFFF8000;
303 int dmx = pb & 0x7FFF;
304 if(pb & 0x8000)
305 dmx |= 0xFFFF8000;
306 int dy = pc & 0x7FFF;
307 if(pc & 0x8000)
308 dy |= 0xFFFF8000;
309 int dmy = pd & 0x7FFF;
310 if(pd & 0x8000)
311 dmy |= 0xFFFF8000;
313 if(VCOUNT == 0)
314 changed = 3;
316 if(changed & 1) {
317 *currentX = (x_l) | ((x_h & 0x07FF)<<16);
318 if(x_h & 0x0800)
319 *currentX |= 0xF8000000;
320 } else {
321 *currentX += dmx;
324 if(changed & 2) {
325 *currentY = (y_l) | ((y_h & 0x07FF)<<16);
326 if(y_h & 0x0800)
327 *currentY |= 0xF8000000;
328 } else {
329 *currentY += dmy;
332 int realX = *currentX;
333 int realY = *currentY;
335 if(control & 0x40) {
336 int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
337 int y = (VCOUNT % mosaicY);
338 realX -= y*dmx;
339 realY -= y*dmy;
342 int xxx = (realX >> 8);
343 int yyy = (realY >> 8);
345 if(control & 0x2000) {
346 xxx %= sizeX;
347 yyy %= sizeY;
348 if(xxx < 0)
349 xxx += sizeX;
350 if(yyy < 0)
351 yyy += sizeY;
354 if(control & 0x80) {
355 for(int x = 0; x < 240; x++) {
356 if(xxx < 0 ||
357 yyy < 0 ||
358 xxx >= sizeX ||
359 yyy >= sizeY) {
360 line[x] = 0x80000000;
361 } else {
362 int tile = screenBase[(xxx>>3) + (yyy>>3)*(sizeX>>3)];
364 int tileX = (xxx & 7);
365 int tileY = yyy & 7;
367 u8 color = charBase[(tile<<6) + (tileY<<3) + tileX];
369 line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000;
371 realX += dx;
372 realY += dy;
374 xxx = (realX >> 8);
375 yyy = (realY >> 8);
377 if(control & 0x2000) {
378 xxx %= sizeX;
379 yyy %= sizeY;
380 if(xxx < 0)
381 xxx += sizeX;
382 if(yyy < 0)
383 yyy += sizeY;
386 } else {
387 for(int x = 0; x < 240; x++) {
388 if(xxx < 0 ||
389 yyy < 0 ||
390 xxx >= sizeX ||
391 yyy >= sizeY) {
392 line[x] = 0x80000000;
393 } else {
394 int tile = screenBase[(xxx>>3) + (yyy>>3)*(sizeX>>3)];
396 int tileX = (xxx & 7);
397 int tileY = yyy & 7;
399 u8 color = charBase[(tile<<6) + (tileY<<3) + tileX];
401 line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000;
403 realX += dx;
404 realY += dy;
406 xxx = (realX >> 8);
407 yyy = (realY >> 8);
409 if(control & 0x2000) {
410 xxx %= sizeX;
411 yyy %= sizeY;
412 if(xxx < 0)
413 xxx += sizeX;
414 if(yyy < 0)
415 yyy += sizeY;
420 if(control & 0x40) {
421 int mosaicX = (MOSAIC & 0xF) + 1;
422 if(mosaicX > 1) {
423 int m = 1;
424 for(int i = 0; i < 239; i++) {
425 line[i+1] = line[i];
426 m++;
427 if(m == mosaicX) {
428 m = 1;
429 i++;
436 static inline void gfxDrawRotScreen16Bit(u16 control,
437 u16 x_l, u16 x_h,
438 u16 y_l, u16 y_h,
439 u16 pa, u16 pb,
440 u16 pc, u16 pd,
441 int *currentX, int *currentY,
442 int changed,
443 u32 *line)
445 u16 *screenBase = (u16 *)&vram[0];
446 int prio = ((control & 3) << 25) + 0x1000000;
447 int sizeX = 240;
448 int sizeY = 160;
450 int startX = (x_l) | ((x_h & 0x07FF)<<16);
451 if(x_h & 0x0800)
452 startX |= 0xF8000000;
453 int startY = (y_l) | ((y_h & 0x07FF)<<16);
454 if(y_h & 0x0800)
455 startY |= 0xF8000000;
457 int dx = pa & 0x7FFF;
458 if(pa & 0x8000)
459 dx |= 0xFFFF8000;
460 int dmx = pb & 0x7FFF;
461 if(pb & 0x8000)
462 dmx |= 0xFFFF8000;
463 int dy = pc & 0x7FFF;
464 if(pc & 0x8000)
465 dy |= 0xFFFF8000;
466 int dmy = pd & 0x7FFF;
467 if(pd & 0x8000)
468 dmy |= 0xFFFF8000;
470 if(VCOUNT == 0)
471 changed = 3;
473 if(changed & 1) {
474 *currentX = (x_l) | ((x_h & 0x07FF)<<16);
475 if(x_h & 0x0800)
476 *currentX |= 0xF8000000;
477 } else
478 *currentX += dmx;
480 if(changed & 2) {
481 *currentY = (y_l) | ((y_h & 0x07FF)<<16);
482 if(y_h & 0x0800)
483 *currentY |= 0xF8000000;
484 } else {
485 *currentY += dmy;
488 int realX = *currentX;
489 int realY = *currentY;
491 if(control & 0x40) {
492 int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
493 int y = (VCOUNT % mosaicY);
494 realX -= y*dmx;
495 realY -= y*dmy;
498 int xxx = (realX >> 8);
499 int yyy = (realY >> 8);
501 for(int x = 0; x < 240; x++) {
502 if(xxx < 0 ||
503 yyy < 0 ||
504 xxx >= sizeX ||
505 yyy >= sizeY) {
506 line[x] = 0x80000000;
507 } else {
508 line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
510 realX += dx;
511 realY += dy;
513 xxx = (realX >> 8);
514 yyy = (realY >> 8);
517 if(control & 0x40) {
518 int mosaicX = (MOSAIC & 0xF) + 1;
519 if(mosaicX > 1) {
520 int m = 1;
521 for(int i = 0; i < 239; i++) {
522 line[i+1] = line[i];
523 m++;
524 if(m == mosaicX) {
525 m = 1;
526 i++;
533 static inline void gfxDrawRotScreen256(u16 control,
534 u16 x_l, u16 x_h,
535 u16 y_l, u16 y_h,
536 u16 pa, u16 pb,
537 u16 pc, u16 pd,
538 int *currentX, int* currentY,
539 int changed,
540 u32 *line)
542 u16 *palette = (u16 *)paletteRAM;
543 u8 *screenBase = (DISPCNT & 0x0010) ? &vram[0xA000] : &vram[0x0000];
544 int prio = ((control & 3) << 25) + 0x1000000;
545 int sizeX = 240;
546 int sizeY = 160;
548 int startX = (x_l) | ((x_h & 0x07FF)<<16);
549 if(x_h & 0x0800)
550 startX |= 0xF8000000;
551 int startY = (y_l) | ((y_h & 0x07FF)<<16);
552 if(y_h & 0x0800)
553 startY |= 0xF8000000;
555 int dx = pa & 0x7FFF;
556 if(pa & 0x8000)
557 dx |= 0xFFFF8000;
558 int dmx = pb & 0x7FFF;
559 if(pb & 0x8000)
560 dmx |= 0xFFFF8000;
561 int dy = pc & 0x7FFF;
562 if(pc & 0x8000)
563 dy |= 0xFFFF8000;
564 int dmy = pd & 0x7FFF;
565 if(pd & 0x8000)
566 dmy |= 0xFFFF8000;
568 if(VCOUNT == 0)
569 changed = 3;
571 if(changed & 1) {
572 *currentX = (x_l) | ((x_h & 0x07FF)<<16);
573 if(x_h & 0x0800)
574 *currentX |= 0xF8000000;
575 } else {
576 *currentX += dmx;
579 if(changed & 2) {
580 *currentY = (y_l) | ((y_h & 0x07FF)<<16);
581 if(y_h & 0x0800)
582 *currentY |= 0xF8000000;
583 } else {
584 *currentY += dmy;
587 int realX = *currentX;
588 int realY = *currentY;
590 if(control & 0x40) {
591 int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
592 int y = (VCOUNT / mosaicY) * mosaicY;
593 realX = startX + y*dmx;
594 realY = startY + y*dmy;
597 int xxx = (realX >> 8);
598 int yyy = (realY >> 8);
600 for(int x = 0; x < 240; x++) {
601 if(xxx < 0 ||
602 yyy < 0 ||
603 xxx >= sizeX ||
604 yyy >= sizeY) {
605 line[x] = 0x80000000;
606 } else {
607 u8 color = screenBase[yyy * 240 + xxx];
609 line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000;
611 realX += dx;
612 realY += dy;
614 xxx = (realX >> 8);
615 yyy = (realY >> 8);
618 if(control & 0x40) {
619 int mosaicX = (MOSAIC & 0xF) + 1;
620 if(mosaicX > 1) {
621 int m = 1;
622 for(int i = 0; i < 239; i++) {
623 line[i+1] = line[i];
624 m++;
625 if(m == mosaicX) {
626 m = 1;
627 i++;
634 static inline void gfxDrawRotScreen16Bit160(u16 control,
635 u16 x_l, u16 x_h,
636 u16 y_l, u16 y_h,
637 u16 pa, u16 pb,
638 u16 pc, u16 pd,
639 int *currentX, int *currentY,
640 int changed,
641 u32 *line)
643 u16 *screenBase = (DISPCNT & 0x0010) ? (u16 *)&vram[0xa000] :
644 (u16 *)&vram[0];
645 int prio = ((control & 3) << 25) + 0x1000000;
646 int sizeX = 160;
647 int sizeY = 128;
649 int startX = (x_l) | ((x_h & 0x07FF)<<16);
650 if(x_h & 0x0800)
651 startX |= 0xF8000000;
652 int startY = (y_l) | ((y_h & 0x07FF)<<16);
653 if(y_h & 0x0800)
654 startY |= 0xF8000000;
656 int dx = pa & 0x7FFF;
657 if(pa & 0x8000)
658 dx |= 0xFFFF8000;
659 int dmx = pb & 0x7FFF;
660 if(pb & 0x8000)
661 dmx |= 0xFFFF8000;
662 int dy = pc & 0x7FFF;
663 if(pc & 0x8000)
664 dy |= 0xFFFF8000;
665 int dmy = pd & 0x7FFF;
666 if(pd & 0x8000)
667 dmy |= 0xFFFF8000;
669 if(VCOUNT == 0)
670 changed = 3;
672 if(changed & 1) {
673 *currentX = (x_l) | ((x_h & 0x07FF)<<16);
674 if(x_h & 0x0800)
675 *currentX |= 0xF8000000;
676 } else {
677 *currentX += dmx;
680 if(changed & 2) {
681 *currentY = (y_l) | ((y_h & 0x07FF)<<16);
682 if(y_h & 0x0800)
683 *currentY |= 0xF8000000;
684 } else {
685 *currentY += dmy;
688 int realX = *currentX;
689 int realY = *currentY;
691 if(control & 0x40) {
692 int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
693 int y = (VCOUNT / mosaicY) * mosaicY;
694 realX = startX + y*dmx;
695 realY = startY + y*dmy;
698 int xxx = (realX >> 8);
699 int yyy = (realY >> 8);
701 for(int x = 0; x < 240; x++) {
702 if(xxx < 0 ||
703 yyy < 0 ||
704 xxx >= sizeX ||
705 yyy >= sizeY) {
706 line[x] = 0x80000000;
707 } else {
708 line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
710 realX += dx;
711 realY += dy;
713 xxx = (realX >> 8);
714 yyy = (realY >> 8);
717 if(control & 0x40) {
718 int mosaicX = (MOSAIC & 0xF) + 1;
719 if(mosaicX > 1) {
720 int m = 1;
721 for(int i = 0; i < 239; i++) {
722 line[i+1] = line[i];
723 m++;
724 if(m == mosaicX) {
725 m = 1;
726 i++;
733 static inline void gfxDrawSprites(u32 *lineOBJ)
735 // lineOBJpix is used to keep track of the drawn OBJs
736 // and to stop drawing them if the 'maximum number of OBJ per line'
737 // has been reached.
738 int lineOBJpix = (DISPCNT & 0x20) ? 954 : 1226;
739 int m=0;
740 gfxClearArray(lineOBJ);
741 if(layerEnable & 0x1000) {
742 u16 *sprites = (u16 *)oam;
743 u16 *spritePalette = &((u16 *)paletteRAM)[256];
744 int mosaicY = ((MOSAIC & 0xF000)>>12) + 1;
745 int mosaicX = ((MOSAIC & 0xF00)>>8) + 1;
746 for(int x = 0; x < 128 ; x++) {
747 u16 a0 = READ16LE(sprites++);
748 u16 a1 = READ16LE(sprites++);
749 u16 a2 = READ16LE(sprites++);
750 sprites++;
752 lineOBJpixleft[x]=lineOBJpix;
754 lineOBJpix-=2;
755 if (lineOBJpix<=0)
756 continue;
758 if ((a0 & 0x0c00) == 0x0c00)
759 a0 &=0xF3FF;
761 if ((a0>>14) == 3)
763 a0 &= 0x3FFF;
764 a1 &= 0x3FFF;
767 int sizeX = 8<<(a1>>14);
768 int sizeY = sizeX;
770 if ((a0>>14) & 1)
772 if (sizeX<32)
773 sizeX<<=1;
774 if (sizeY>8)
775 sizeY>>=1;
777 else if ((a0>>14) & 2)
779 if (sizeX>8)
780 sizeX>>=1;
781 if (sizeY<32)
782 sizeY<<=1;
785 #ifdef SPRITE_DEBUG
786 int maskX = sizeX-1;
787 int maskY = sizeY-1;
788 #endif
790 int sy = (a0 & 255);
791 int sx = (a1 & 0x1FF);
793 // computes ticks used by OBJ-WIN if OBJWIN is enabled
794 if (((a0 & 0x0c00) == 0x0800) && (layerEnable & 0x8000))
796 if ((a0 & 0x0300) == 0x0300)
798 sizeX<<=1;
799 sizeY<<=1;
801 if((sy+sizeY) > 256)
802 sy -= 256;
803 if ((sx+sizeX)> 512)
804 sx-=512;
805 if (sx<0)
807 sizeX+=sx;
808 sx = 0;
810 else if ((sx+sizeX)>240)
811 sizeX=240-sx;
812 if ((VCOUNT>=sy) && (VCOUNT<sy+sizeY) && (sx<240))
814 if (a0 & 0x0100)
815 lineOBJpix-=8+2*sizeX;
816 else
817 lineOBJpix-=sizeX-2;
819 continue;
821 // else ignores OBJ-WIN if OBJWIN is disabled, and ignored disabled OBJ
822 else
823 if(((a0 & 0x0c00) == 0x0800) || ((a0 & 0x0300) == 0x0200))
824 continue;
826 if (lineOBJpix<0)
827 continue;
831 if(a0 & 0x0100) {
832 int fieldX = sizeX;
833 int fieldY = sizeY;
834 if(a0 & 0x0200) {
835 fieldX <<= 1;
836 fieldY <<= 1;
838 if((sy+fieldY) > 256)
839 sy -= 256;
840 int t = VCOUNT - sy;
841 if((t >= 0) && (t < fieldY)) {
842 int startpix = 0;
843 if ((sx+fieldX)> 512)
845 startpix=512-sx;
847 if (lineOBJpix>0)
848 if((sx < 240) || startpix) {
849 lineOBJpix-=8;
850 // int t2 = t - (fieldY >> 1);
851 int rot = (a1 >> 9) & 0x1F;
852 u16 *OAM = (u16 *)oam;
853 int dx = READ16LE(&OAM[3 + (rot << 4)]);
854 if(dx & 0x8000)
855 dx |= 0xFFFF8000;
856 int dmx = READ16LE(&OAM[7 + (rot << 4)]);
857 if(dmx & 0x8000)
858 dmx |= 0xFFFF8000;
859 int dy = READ16LE(&OAM[11 + (rot << 4)]);
860 if(dy & 0x8000)
861 dy |= 0xFFFF8000;
862 int dmy = READ16LE(&OAM[15 + (rot << 4)]);
863 if(dmy & 0x8000)
864 dmy |= 0xFFFF8000;
866 if(a0 & 0x1000) {
867 t -= (t % mosaicY);
870 int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx
871 + t * dmx;
872 int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy
873 + t * dmy;
875 u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
877 if(a0 & 0x2000) {
878 int c = (a2 & 0x3FF);
879 if((DISPCNT & 7) > 2 && (c < 512))
880 continue;
881 int inc = 32;
882 if(DISPCNT & 0x40)
883 inc = sizeX >> 2;
884 else
885 c &= 0x3FE;
886 for(int x = 0; x < fieldX; x++) {
887 if (x >= startpix)
888 lineOBJpix-=2;
889 if (lineOBJpix<0)
890 continue;
891 int xxx = realX >> 8;
892 int yyy = realY >> 8;
894 if(xxx < 0 || xxx >= sizeX ||
895 yyy < 0 || yyy >= sizeY ||
896 sx >= 240);
897 else {
898 u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
899 + ((yyy & 7)<<3) + ((xxx >> 3)<<6) +
900 (xxx & 7))&0x7FFF)];
901 if ((color==0) && (((prio >> 25)&3) <
902 ((lineOBJ[sx]>>25)&3))) {
903 lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
904 if((a0 & 0x1000) && m)
905 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
906 } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
907 lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio;
908 if((a0 & 0x1000) && m)
909 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
912 if (a0 & 0x1000) {
913 m++;
914 if (m==mosaicX)
915 m=0;
917 #ifdef SPRITE_DEBUG
918 if(t == 0 || t == maskY || x == 0 || x == maskX)
919 lineOBJ[sx] = 0x001F;
920 #endif
922 sx = (sx+1)&511;
923 realX += dx;
924 realY += dy;
926 } else {
927 int c = (a2 & 0x3FF);
928 if((DISPCNT & 7) > 2 && (c < 512))
929 continue;
931 int inc = 32;
932 if(DISPCNT & 0x40)
933 inc = sizeX >> 3;
934 int palette = (a2 >> 8) & 0xF0;
935 for(int x = 0; x < fieldX; x++) {
936 if (x >= startpix)
937 lineOBJpix-=2;
938 if (lineOBJpix<0)
939 continue;
940 int xxx = realX >> 8;
941 int yyy = realY >> 8;
942 if(xxx < 0 || xxx >= sizeX ||
943 yyy < 0 || yyy >= sizeY ||
944 sx >= 240);
945 else {
946 u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
947 + ((yyy & 7)<<2) + ((xxx >> 3)<<5) +
948 ((xxx & 7)>>1))&0x7FFF)];
949 if(xxx & 1)
950 color >>= 4;
951 else
952 color &= 0x0F;
954 if ((color==0) && (((prio >> 25)&3) <
955 ((lineOBJ[sx]>>25)&3))) {
956 lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
957 if((a0 & 0x1000) && m)
958 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
959 } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
960 lineOBJ[sx] = READ16LE(&spritePalette[palette+color]) | prio;
961 if((a0 & 0x1000) && m)
962 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
965 if((a0 & 0x1000) && m) {
966 m++;
967 if (m==mosaicX)
968 m=0;
971 #ifdef SPRITE_DEBUG
972 if(t == 0 || t == maskY || x == 0 || x == maskX)
973 lineOBJ[sx] = 0x001F;
974 #endif
975 sx = (sx+1)&511;
976 realX += dx;
977 realY += dy;
983 } else {
984 if(sy+sizeY > 256)
985 sy -= 256;
986 int t = VCOUNT - sy;
987 if((t >= 0) && (t < sizeY)) {
988 int startpix = 0;
989 if ((sx+sizeX)> 512)
991 startpix=512-sx;
993 if((sx < 240) || startpix) {
994 lineOBJpix+=2;
995 if(a0 & 0x2000) {
996 if(a1 & 0x2000)
997 t = sizeY - t - 1;
998 int c = (a2 & 0x3FF);
999 if((DISPCNT & 7) > 2 && (c < 512))
1000 continue;
1002 int inc = 32;
1003 if(DISPCNT & 0x40) {
1004 inc = sizeX >> 2;
1005 } else {
1006 c &= 0x3FE;
1008 int xxx = 0;
1009 if(a1 & 0x1000)
1010 xxx = sizeX-1;
1012 if(a0 & 0x1000) {
1013 t -= (t % mosaicY);
1016 int address = 0x10000 + ((((c+ (t>>3) * inc) << 5)
1017 + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7)) & 0x7FFF);
1019 if(a1 & 0x1000)
1020 xxx = 7;
1021 u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
1023 for(int xx = 0; xx < sizeX; xx++) {
1024 if (xx >= startpix)
1025 lineOBJpix--;
1026 if (lineOBJpix<0)
1027 continue;
1028 if(sx < 240) {
1029 u8 color = vram[address];
1030 if ((color==0) && (((prio >> 25)&3) <
1031 ((lineOBJ[sx]>>25)&3))) {
1032 lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
1033 if((a0 & 0x1000) && m)
1034 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
1035 } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
1036 lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio;
1037 if((a0 & 0x1000) && m)
1038 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
1041 if (a0 & 0x1000) {
1042 m++;
1043 if (m==mosaicX)
1044 m=0;
1047 #ifdef SPRITE_DEBUG
1048 if(t == 0 || t == maskY || xx == 0 || xx == maskX)
1049 lineOBJ[sx] = 0x001F;
1050 #endif
1053 sx = (sx+1) & 511;
1054 if(a1 & 0x1000) {
1055 xxx--;
1056 address--;
1057 if(xxx == -1) {
1058 address -= 56;
1059 xxx = 7;
1061 if(address < 0x10000)
1062 address += 0x8000;
1063 } else {
1064 xxx++;
1065 address++;
1066 if(xxx == 8) {
1067 address += 56;
1068 xxx = 0;
1070 if(address > 0x17fff)
1071 address -= 0x8000;
1074 } else {
1075 if(a1 & 0x2000)
1076 t = sizeY - t - 1;
1077 int c = (a2 & 0x3FF);
1078 if((DISPCNT & 7) > 2 && (c < 512))
1079 continue;
1081 int inc = 32;
1082 if(DISPCNT & 0x40) {
1083 inc = sizeX >> 3;
1085 int xxx = 0;
1086 if(a1 & 0x1000)
1087 xxx = sizeX - 1;
1089 if(a0 & 0x1000) {
1090 t -= (t % mosaicY);
1093 int address = 0x10000 + ((((c + (t>>3) * inc)<<5)
1094 + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7FFF);
1095 u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
1096 int palette = (a2 >> 8) & 0xF0;
1097 if(a1 & 0x1000) {
1098 xxx = 7;
1099 for(int xx = sizeX - 1; xx >= 0; xx--) {
1100 if (xx >= startpix)
1101 lineOBJpix--;
1102 if (lineOBJpix<0)
1103 continue;
1104 if(sx < 240) {
1105 u8 color = vram[address];
1106 if(xx & 1) {
1107 color = (color >> 4);
1108 } else
1109 color &= 0x0F;
1111 if ((color==0) && (((prio >> 25)&3) <
1112 ((lineOBJ[sx]>>25)&3))) {
1113 lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
1114 if((a0 & 0x1000) && m)
1115 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
1116 } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
1117 lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio;
1118 if((a0 & 0x1000) && m)
1119 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
1122 if (a0 & 0x1000) {
1123 m++;
1124 if (m==mosaicX)
1125 m=0;
1127 #ifdef SPRITE_DEBUG
1128 if(t == 0 || t == maskY || xx == 0 || xx == maskX)
1129 lineOBJ[sx] = 0x001F;
1130 #endif
1131 sx = (sx+1) & 511;
1132 xxx--;
1133 if(!(xx & 1))
1134 address--;
1135 if(xxx == -1) {
1136 xxx = 7;
1137 address -= 28;
1139 if(address < 0x10000)
1140 address += 0x8000;
1142 } else {
1143 for(int xx = 0; xx < sizeX; xx++) {
1144 if (xx >= startpix)
1145 lineOBJpix--;
1146 if (lineOBJpix<0)
1147 continue;
1148 if(sx < 240) {
1149 u8 color = vram[address];
1150 if(xx & 1) {
1151 color = (color >> 4);
1152 } else
1153 color &= 0x0F;
1155 if ((color==0) && (((prio >> 25)&3) <
1156 ((lineOBJ[sx]>>25)&3))) {
1157 lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
1158 if((a0 & 0x1000) && m)
1159 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
1160 } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
1161 lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio;
1162 if((a0 & 0x1000) && m)
1163 lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
1167 if (a0 & 0x1000) {
1168 m++;
1169 if (m==mosaicX)
1170 m=0;
1172 #ifdef SPRITE_DEBUG
1173 if(t == 0 || t == maskY || xx == 0 || xx == maskX)
1174 lineOBJ[sx] = 0x001F;
1175 #endif
1176 sx = (sx+1) & 511;
1177 xxx++;
1178 if(xx & 1)
1179 address++;
1180 if(xxx == 8) {
1181 address += 28;
1182 xxx = 0;
1184 if(address > 0x17fff)
1185 address -= 0x8000;
1196 static inline void gfxDrawOBJWin(u32 *lineOBJWin)
1198 gfxClearArray(lineOBJWin);
1199 if((layerEnable & 0x9000) == 0x9000) {
1200 u16 *sprites = (u16 *)oam;
1201 // u16 *spritePalette = &((u16 *)paletteRAM)[256];
1202 for(int x = 0; x < 128 ; x++) {
1203 int lineOBJpix = lineOBJpixleft[x];
1204 u16 a0 = READ16LE(sprites++);
1205 u16 a1 = READ16LE(sprites++);
1206 u16 a2 = READ16LE(sprites++);
1207 sprites++;
1209 if (lineOBJpix<=0)
1210 continue;
1212 // ignores non OBJ-WIN and disabled OBJ-WIN
1213 if(((a0 & 0x0c00) != 0x0800) || ((a0 & 0x0300) == 0x0200))
1214 continue;
1216 if ((a0 & 0x0c00) == 0x0c00)
1217 a0 &=0xF3FF;
1219 if ((a0>>14) == 3)
1221 a0 &= 0x3FFF;
1222 a1 &= 0x3FFF;
1225 int sizeX = 8<<(a1>>14);
1226 int sizeY = sizeX;
1228 if ((a0>>14) & 1)
1230 if (sizeX<32)
1231 sizeX<<=1;
1232 if (sizeY>8)
1233 sizeY>>=1;
1235 else if ((a0>>14) & 2)
1237 if (sizeX>8)
1238 sizeX>>=1;
1239 if (sizeY<32)
1240 sizeY<<=1;
1243 int sy = (a0 & 255);
1245 if(a0 & 0x0100) {
1246 int fieldX = sizeX;
1247 int fieldY = sizeY;
1248 if(a0 & 0x0200) {
1249 fieldX <<= 1;
1250 fieldY <<= 1;
1252 if((sy+fieldY) > 256)
1253 sy -= 256;
1254 int t = VCOUNT - sy;
1255 if((t >= 0) && (t < fieldY)) {
1256 int sx = (a1 & 0x1FF);
1257 int startpix = 0;
1258 if ((sx+fieldX)> 512)
1260 startpix=512-sx;
1262 if((sx < 240) || startpix) {
1263 lineOBJpix-=8;
1264 // int t2 = t - (fieldY >> 1);
1265 int rot = (a1 >> 9) & 0x1F;
1266 u16 *OAM = (u16 *)oam;
1267 int dx = READ16LE(&OAM[3 + (rot << 4)]);
1268 if(dx & 0x8000)
1269 dx |= 0xFFFF8000;
1270 int dmx = READ16LE(&OAM[7 + (rot << 4)]);
1271 if(dmx & 0x8000)
1272 dmx |= 0xFFFF8000;
1273 int dy = READ16LE(&OAM[11 + (rot << 4)]);
1274 if(dy & 0x8000)
1275 dy |= 0xFFFF8000;
1276 int dmy = READ16LE(&OAM[15 + (rot << 4)]);
1277 if(dmy & 0x8000)
1278 dmy |= 0xFFFF8000;
1280 int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx
1281 + t * dmx;
1282 int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy
1283 + t * dmy;
1285 // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
1287 if(a0 & 0x2000) {
1288 int c = (a2 & 0x3FF);
1289 if((DISPCNT & 7) > 2 && (c < 512))
1290 continue;
1291 int inc = 32;
1292 if(DISPCNT & 0x40)
1293 inc = sizeX >> 2;
1294 else
1295 c &= 0x3FE;
1296 for(int x = 0; x < fieldX; x++) {
1297 if (x >= startpix)
1298 lineOBJpix-=2;
1299 if (lineOBJpix<0)
1300 continue;
1301 int xxx = realX >> 8;
1302 int yyy = realY >> 8;
1304 if(xxx < 0 || xxx >= sizeX ||
1305 yyy < 0 || yyy >= sizeY ||
1306 sx >= 240) {
1307 } else {
1308 u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
1309 + ((yyy & 7)<<3) + ((xxx >> 3)<<6) +
1310 (xxx & 7))&0x7fff)];
1311 if(color) {
1312 lineOBJWin[sx] = 1;
1315 sx = (sx+1)&511;
1316 realX += dx;
1317 realY += dy;
1319 } else {
1320 int c = (a2 & 0x3FF);
1321 if((DISPCNT & 7) > 2 && (c < 512))
1322 continue;
1324 int inc = 32;
1325 if(DISPCNT & 0x40)
1326 inc = sizeX >> 3;
1327 // int palette = (a2 >> 8) & 0xF0;
1328 for(int x = 0; x < fieldX; x++) {
1329 if (x >= startpix)
1330 lineOBJpix-=2;
1331 if (lineOBJpix<0)
1332 continue;
1333 int xxx = realX >> 8;
1334 int yyy = realY >> 8;
1336 // if(x == 0 || x == (sizeX-1) ||
1337 // t == 0 || t == (sizeY-1)) {
1338 // lineOBJ[sx] = 0x001F | prio;
1339 // } else {
1340 if(xxx < 0 || xxx >= sizeX ||
1341 yyy < 0 || yyy >= sizeY ||
1342 sx >= 240) {
1343 } else {
1344 u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
1345 + ((yyy & 7)<<2) + ((xxx >> 3)<<5) +
1346 ((xxx & 7)>>1))&0x7fff)];
1347 if(xxx & 1)
1348 color >>= 4;
1349 else
1350 color &= 0x0F;
1352 if(color) {
1353 lineOBJWin[sx] = 1;
1356 // }
1357 sx = (sx+1)&511;
1358 realX += dx;
1359 realY += dy;
1364 } else {
1365 if((sy+sizeY) > 256)
1366 sy -= 256;
1367 int t = VCOUNT - sy;
1368 if((t >= 0) && (t < sizeY)) {
1369 int sx = (a1 & 0x1FF);
1370 int startpix = 0;
1371 if ((sx+sizeX)> 512)
1373 startpix=512-sx;
1375 if((sx < 240) || startpix) {
1376 lineOBJpix+=2;
1377 if(a0 & 0x2000) {
1378 if(a1 & 0x2000)
1379 t = sizeY - t - 1;
1380 int c = (a2 & 0x3FF);
1381 if((DISPCNT & 7) > 2 && (c < 512))
1382 continue;
1384 int inc = 32;
1385 if(DISPCNT & 0x40) {
1386 inc = sizeX >> 2;
1387 } else {
1388 c &= 0x3FE;
1390 int xxx = 0;
1391 if(a1 & 0x1000)
1392 xxx = sizeX-1;
1393 int address = 0x10000 + ((((c+ (t>>3) * inc) << 5)
1394 + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7))&0x7fff);
1395 if(a1 & 0x1000)
1396 xxx = 7;
1397 // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
1398 for(int xx = 0; xx < sizeX; xx++) {
1399 if (xx >= startpix)
1400 lineOBJpix--;
1401 if (lineOBJpix<0)
1402 continue;
1403 if(sx < 240) {
1404 u8 color = vram[address];
1405 if(color) {
1406 lineOBJWin[sx] = 1;
1410 sx = (sx+1) & 511;
1411 if(a1 & 0x1000) {
1412 xxx--;
1413 address--;
1414 if(xxx == -1) {
1415 address -= 56;
1416 xxx = 7;
1418 if(address < 0x10000)
1419 address += 0x8000;
1420 } else {
1421 xxx++;
1422 address++;
1423 if(xxx == 8) {
1424 address += 56;
1425 xxx = 0;
1427 if(address > 0x17fff)
1428 address -= 0x8000;
1431 } else {
1432 if(a1 & 0x2000)
1433 t = sizeY - t - 1;
1434 int c = (a2 & 0x3FF);
1435 if((DISPCNT & 7) > 2 && (c < 512))
1436 continue;
1438 int inc = 32;
1439 if(DISPCNT & 0x40) {
1440 inc = sizeX >> 3;
1442 int xxx = 0;
1443 if(a1 & 0x1000)
1444 xxx = sizeX - 1;
1445 int address = 0x10000 + ((((c + (t>>3) * inc)<<5)
1446 + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7fff);
1447 // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
1448 // int palette = (a2 >> 8) & 0xF0;
1449 if(a1 & 0x1000) {
1450 xxx = 7;
1451 for(int xx = sizeX - 1; xx >= 0; xx--) {
1452 if (xx >= startpix)
1453 lineOBJpix--;
1454 if (lineOBJpix<0)
1455 continue;
1456 if(sx < 240) {
1457 u8 color = vram[address];
1458 if(xx & 1) {
1459 color = (color >> 4);
1460 } else
1461 color &= 0x0F;
1463 if(color) {
1464 lineOBJWin[sx] = 1;
1467 sx = (sx+1) & 511;
1468 xxx--;
1469 if(!(xx & 1))
1470 address--;
1471 if(xxx == -1) {
1472 xxx = 7;
1473 address -= 28;
1475 if(address < 0x10000)
1476 address += 0x8000;
1478 } else {
1479 for(int xx = 0; xx < sizeX; xx++) {
1480 if (xx >= startpix)
1481 lineOBJpix--;
1482 if (lineOBJpix<0)
1483 continue;
1484 if(sx < 240) {
1485 u8 color = vram[address];
1486 if(xx & 1) {
1487 color = (color >> 4);
1488 } else
1489 color &= 0x0F;
1491 if(color) {
1492 lineOBJWin[sx] = 1;
1495 sx = (sx+1) & 511;
1496 xxx++;
1497 if(xx & 1)
1498 address++;
1499 if(xxx == 8) {
1500 address += 28;
1501 xxx = 0;
1503 if(address > 0x17fff)
1504 address -= 0x8000;
1515 static inline u32 gfxIncreaseBrightnessU(u32 color, int coeff)
1517 int r = (color & 0x1F);
1518 int g = ((color >> 5) & 0x1F);
1519 int b = ((color >> 10) & 0x1F);
1521 r = r + (((31 - r) * coeff) >> 4);
1522 g = g + (((31 - g) * coeff) >> 4);
1523 b = b + (((31 - b) * coeff) >> 4);
1524 if(r > 31)
1525 r = 31;
1526 if(g > 31)
1527 g = 31;
1528 if(b > 31)
1529 b = 31;
1530 color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
1531 return color;
1534 static inline void gfxIncreaseBrightness(u32 *line, int coeff)
1536 for(int x = 0; x < 240; x++) {
1537 u32 color = *line;
1538 int r = (color & 0x1F);
1539 int g = ((color >> 5) & 0x1F);
1540 int b = ((color >> 10) & 0x1F);
1542 r = r + (((31 - r) * coeff) >> 4);
1543 g = g + (((31 - g) * coeff) >> 4);
1544 b = b + (((31 - b) * coeff) >> 4);
1545 if(r > 31)
1546 r = 31;
1547 if(g > 31)
1548 g = 31;
1549 if(b > 31)
1550 b = 31;
1551 *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
1555 static inline u32 gfxDecreaseBrightnessU(u32 color, int coeff)
1557 int r = (color & 0x1F);
1558 int g = ((color >> 5) & 0x1F);
1559 int b = ((color >> 10) & 0x1F);
1561 r = r - ((r * coeff) >> 4);
1562 g = g - ((g * coeff) >> 4);
1563 b = b - ((b * coeff) >> 4);
1564 if(r < 0)
1565 r = 0;
1566 if(g < 0)
1567 g = 0;
1568 if(b < 0)
1569 b = 0;
1570 color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
1572 return color;
1575 static inline void gfxDecreaseBrightness(u32 *line, int coeff)
1577 for(int x = 0; x < 240; x++) {
1578 u32 color = *line;
1579 int r = (color & 0x1F);
1580 int g = ((color >> 5) & 0x1F);
1581 int b = ((color >> 10) & 0x1F);
1583 r = r - ((r * coeff) >> 4);
1584 g = g - ((g * coeff) >> 4);
1585 b = b - ((b * coeff) >> 4);
1586 if(r < 0)
1587 r = 0;
1588 if(g < 0)
1589 g = 0;
1590 if(b < 0)
1591 b = 0;
1592 *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
1596 static inline u32 gfxAlphaBlendU(u32 color, u32 color2, int ca, int cb)
1598 if(color < 0x80000000) {
1599 int r = (color & 0x1F);
1600 int g = ((color >> 5) & 0x1F);
1601 int b = ((color >> 10) & 0x1F);
1602 int r0 = (color2 & 0x1F);
1603 int g0 = ((color2 >> 5) & 0x1F);
1604 int b0 = ((color2 >> 10) & 0x1F);
1606 r = ((r * ca) + (r0 * cb)) >> 4;
1607 g = ((g * ca) + (g0 * cb)) >> 4;
1608 b = ((b * ca) + (b0 * cb)) >> 4;
1610 if(r > 31)
1611 r = 31;
1612 if(g > 31)
1613 g = 31;
1614 if(b > 31)
1615 b = 31;
1617 return (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
1619 return color;
1622 static inline void gfxAlphaBlend(u32 *ta, u32 *tb, int ca, int cb)
1624 for(int x = 0; x < 240; x++) {
1625 u32 color = *ta;
1626 if(color < 0x80000000) {
1627 int r = (color & 0x1F);
1628 int g = ((color >> 5) & 0x1F);
1629 int b = ((color >> 10) & 0x1F);
1630 u32 color2 = (*tb++);
1631 int r0 = (color2 & 0x1F);
1632 int g0 = ((color2 >> 5) & 0x1F);
1633 int b0 = ((color2 >> 10) & 0x1F);
1635 r = ((r * ca) + (r0 * cb)) >> 4;
1636 g = ((g * ca) + (g0 * cb)) >> 4;
1637 b = ((b * ca) + (b0 * cb)) >> 4;
1639 if(r > 31)
1640 r = 31;
1641 if(g > 31)
1642 g = 31;
1643 if(b > 31)
1644 b = 31;
1646 *ta++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
1647 } else {
1648 ta++;
1649 tb++;
1654 #endif // VBA_GFX_H