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)
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.
29 //#define SPRITE_DEBUG
31 static void gfxDrawTextScreen(u16
, u16
, u16
, u32
*);
32 static void gfxDrawRotScreen(u16
,
40 static void gfxDrawRotScreen16Bit(u16
,
48 static void gfxDrawRotScreen256(u16
,
56 static void gfxDrawRotScreen16Bit160(u16
,
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();
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
;
110 extern int gfxBG2LastX
;
111 extern int gfxBG2LastY
;
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
,
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;
134 switch((control
>> 14) & 3) {
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;
160 if((VCOUNT
% mosaicY
) != 0) {
161 mosaicY
= (VCOUNT
/ mosaicY
) * mosaicY
;
162 yyy
= (vofs
+ mosaicY
) & maskY
;
166 if(yyy
> 255 && sizeY
> 256) {
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);
188 u8 color
= charBase
[tile
* 64 + tileY
* 8 + tileX
];
190 line
[x
] = color
? (READ16LE(&palette
[color
]) | prio
): 0x80000000;
195 } else if(tileX
== 7)
200 screenSource
= screenBase
+ 0x400 + yshift
;
202 screenSource
= screenBase
+ yshift
;
205 } else if(xxx
>= sizeX
) {
207 screenSource
= screenBase
+ yshift
;
211 u16
*screenSource
= screenBase
+ 0x400*(xxx
>>8)+((xxx
&255)>>3) +
213 for(int x
= 0; x
< 240; x
++) {
214 u16 data
= READ16LE(screenSource
);
216 int tile
= data
& 0x3FF;
217 int tileX
= (xxx
& 7);
225 u8 color
= charBase
[(tile
<<5) + (tileY
<<2) + (tileX
>>1)];
228 color
= (color
>> 4);
233 int pal
= (READ16LE(screenSource
)>>8) & 0xF0;
234 line
[x
] = color
? (READ16LE(&palette
[pal
+ color
])|prio
): 0x80000000;
239 } else if(tileX
== 7)
244 screenSource
= screenBase
+ 0x400 + yshift
;
246 screenSource
= screenBase
+ yshift
;
249 } else if(xxx
>= sizeX
) {
251 screenSource
= screenBase
+ yshift
;
258 for(int i
= 0; i
< 239; i
++) {
270 static inline void gfxDrawRotScreen(u16 control
,
275 int *currentX
, int *currentY
,
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;
286 switch((control
>> 14) & 3) {
296 sizeX
= sizeY
= 1024;
300 int dx
= pa
& 0x7FFF;
303 int dmx
= pb
& 0x7FFF;
306 int dy
= pc
& 0x7FFF;
309 int dmy
= pd
& 0x7FFF;
317 *currentX
= (x_l
) | ((x_h
& 0x07FF)<<16);
319 *currentX
|= 0xF8000000;
325 *currentY
= (y_l
) | ((y_h
& 0x07FF)<<16);
327 *currentY
|= 0xF8000000;
332 int realX
= *currentX
;
333 int realY
= *currentY
;
336 int mosaicY
= ((MOSAIC
& 0xF0)>>4) + 1;
337 int y
= (VCOUNT
% mosaicY
);
342 int xxx
= (realX
>> 8);
343 int yyy
= (realY
>> 8);
345 if(control
& 0x2000) {
355 for(int x
= 0; x
< 240; x
++) {
360 line
[x
] = 0x80000000;
362 int tile
= screenBase
[(xxx
>>3) + (yyy
>>3)*(sizeX
>>3)];
364 int tileX
= (xxx
& 7);
367 u8 color
= charBase
[(tile
<<6) + (tileY
<<3) + tileX
];
369 line
[x
] = color
? (READ16LE(&palette
[color
])|prio
): 0x80000000;
377 if(control
& 0x2000) {
387 for(int x
= 0; x
< 240; x
++) {
392 line
[x
] = 0x80000000;
394 int tile
= screenBase
[(xxx
>>3) + (yyy
>>3)*(sizeX
>>3)];
396 int tileX
= (xxx
& 7);
399 u8 color
= charBase
[(tile
<<6) + (tileY
<<3) + tileX
];
401 line
[x
] = color
? (READ16LE(&palette
[color
])|prio
): 0x80000000;
409 if(control
& 0x2000) {
421 int mosaicX
= (MOSAIC
& 0xF) + 1;
424 for(int i
= 0; i
< 239; i
++) {
436 static inline void gfxDrawRotScreen16Bit(u16 control
,
441 int *currentX
, int *currentY
,
445 u16
*screenBase
= (u16
*)&vram
[0];
446 int prio
= ((control
& 3) << 25) + 0x1000000;
450 int startX
= (x_l
) | ((x_h
& 0x07FF)<<16);
452 startX
|= 0xF8000000;
453 int startY
= (y_l
) | ((y_h
& 0x07FF)<<16);
455 startY
|= 0xF8000000;
457 int dx
= pa
& 0x7FFF;
460 int dmx
= pb
& 0x7FFF;
463 int dy
= pc
& 0x7FFF;
466 int dmy
= pd
& 0x7FFF;
474 *currentX
= (x_l
) | ((x_h
& 0x07FF)<<16);
476 *currentX
|= 0xF8000000;
481 *currentY
= (y_l
) | ((y_h
& 0x07FF)<<16);
483 *currentY
|= 0xF8000000;
488 int realX
= *currentX
;
489 int realY
= *currentY
;
492 int mosaicY
= ((MOSAIC
& 0xF0)>>4) + 1;
493 int y
= (VCOUNT
% mosaicY
);
498 int xxx
= (realX
>> 8);
499 int yyy
= (realY
>> 8);
501 for(int x
= 0; x
< 240; x
++) {
506 line
[x
] = 0x80000000;
508 line
[x
] = (READ16LE(&screenBase
[yyy
* sizeX
+ xxx
]) | prio
);
518 int mosaicX
= (MOSAIC
& 0xF) + 1;
521 for(int i
= 0; i
< 239; i
++) {
533 static inline void gfxDrawRotScreen256(u16 control
,
538 int *currentX
, int* currentY
,
542 u16
*palette
= (u16
*)paletteRAM
;
543 u8
*screenBase
= (DISPCNT
& 0x0010) ? &vram
[0xA000] : &vram
[0x0000];
544 int prio
= ((control
& 3) << 25) + 0x1000000;
548 int startX
= (x_l
) | ((x_h
& 0x07FF)<<16);
550 startX
|= 0xF8000000;
551 int startY
= (y_l
) | ((y_h
& 0x07FF)<<16);
553 startY
|= 0xF8000000;
555 int dx
= pa
& 0x7FFF;
558 int dmx
= pb
& 0x7FFF;
561 int dy
= pc
& 0x7FFF;
564 int dmy
= pd
& 0x7FFF;
572 *currentX
= (x_l
) | ((x_h
& 0x07FF)<<16);
574 *currentX
|= 0xF8000000;
580 *currentY
= (y_l
) | ((y_h
& 0x07FF)<<16);
582 *currentY
|= 0xF8000000;
587 int realX
= *currentX
;
588 int realY
= *currentY
;
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
++) {
605 line
[x
] = 0x80000000;
607 u8 color
= screenBase
[yyy
* 240 + xxx
];
609 line
[x
] = color
? (READ16LE(&palette
[color
])|prio
): 0x80000000;
619 int mosaicX
= (MOSAIC
& 0xF) + 1;
622 for(int i
= 0; i
< 239; i
++) {
634 static inline void gfxDrawRotScreen16Bit160(u16 control
,
639 int *currentX
, int *currentY
,
643 u16
*screenBase
= (DISPCNT
& 0x0010) ? (u16
*)&vram
[0xa000] :
645 int prio
= ((control
& 3) << 25) + 0x1000000;
649 int startX
= (x_l
) | ((x_h
& 0x07FF)<<16);
651 startX
|= 0xF8000000;
652 int startY
= (y_l
) | ((y_h
& 0x07FF)<<16);
654 startY
|= 0xF8000000;
656 int dx
= pa
& 0x7FFF;
659 int dmx
= pb
& 0x7FFF;
662 int dy
= pc
& 0x7FFF;
665 int dmy
= pd
& 0x7FFF;
673 *currentX
= (x_l
) | ((x_h
& 0x07FF)<<16);
675 *currentX
|= 0xF8000000;
681 *currentY
= (y_l
) | ((y_h
& 0x07FF)<<16);
683 *currentY
|= 0xF8000000;
688 int realX
= *currentX
;
689 int realY
= *currentY
;
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
++) {
706 line
[x
] = 0x80000000;
708 line
[x
] = (READ16LE(&screenBase
[yyy
* sizeX
+ xxx
]) | prio
);
718 int mosaicX
= (MOSAIC
& 0xF) + 1;
721 for(int i
= 0; i
< 239; 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'
738 int lineOBJpix
= (DISPCNT
& 0x20) ? 954 : 1226;
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
++);
752 lineOBJpixleft
[x
]=lineOBJpix
;
758 if ((a0
& 0x0c00) == 0x0c00)
767 int sizeX
= 8<<(a1
>>14);
777 else if ((a0
>>14) & 2)
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)
810 else if ((sx
+sizeX
)>240)
812 if ((VCOUNT
>=sy
) && (VCOUNT
<sy
+sizeY
) && (sx
<240))
815 lineOBJpix
-=8+2*sizeX
;
821 // else ignores OBJ-WIN if OBJWIN is disabled, and ignored disabled OBJ
823 if(((a0
& 0x0c00) == 0x0800) || ((a0
& 0x0300) == 0x0200))
838 if((sy
+fieldY
) > 256)
841 if((t
>= 0) && (t
< fieldY
)) {
843 if ((sx
+fieldX
)> 512)
848 if((sx
< 240) || startpix
) {
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)]);
856 int dmx
= READ16LE(&OAM
[7 + (rot
<< 4)]);
859 int dy
= READ16LE(&OAM
[11 + (rot
<< 4)]);
862 int dmy
= READ16LE(&OAM
[15 + (rot
<< 4)]);
870 int realX
= ((sizeX
) << 7) - (fieldX
>> 1)*dx
- (fieldY
>>1)*dmx
872 int realY
= ((sizeY
) << 7) - (fieldX
>> 1)*dy
- (fieldY
>>1)*dmy
875 u32 prio
= (((a2
>> 10) & 3) << 25) | ((a0
& 0x0c00)<<6);
878 int c
= (a2
& 0x3FF);
879 if((DISPCNT
& 7) > 2 && (c
< 512))
886 for(int x
= 0; x
< fieldX
; x
++) {
891 int xxx
= realX
>> 8;
892 int yyy
= realY
>> 8;
894 if(xxx
< 0 || xxx
>= sizeX
||
895 yyy
< 0 || yyy
>= sizeY
||
898 u32 color
= vram
[0x10000 + ((((c
+ (yyy
>>3) * inc
)<<5)
899 + ((yyy
& 7)<<3) + ((xxx
>> 3)<<6) +
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
;
918 if(t
== 0 || t
== maskY
|| x
== 0 || x
== maskX
)
919 lineOBJ
[sx
] = 0x001F;
927 int c
= (a2
& 0x3FF);
928 if((DISPCNT
& 7) > 2 && (c
< 512))
934 int palette
= (a2
>> 8) & 0xF0;
935 for(int x
= 0; x
< fieldX
; x
++) {
940 int xxx
= realX
>> 8;
941 int yyy
= realY
>> 8;
942 if(xxx
< 0 || xxx
>= sizeX
||
943 yyy
< 0 || yyy
>= sizeY
||
946 u32 color
= vram
[0x10000 + ((((c
+ (yyy
>>3) * inc
)<<5)
947 + ((yyy
& 7)<<2) + ((xxx
>> 3)<<5) +
948 ((xxx
& 7)>>1))&0x7FFF)];
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
) {
972 if(t
== 0 || t
== maskY
|| x
== 0 || x
== maskX
)
973 lineOBJ
[sx
] = 0x001F;
987 if((t
>= 0) && (t
< sizeY
)) {
993 if((sx
< 240) || startpix
) {
998 int c
= (a2
& 0x3FF);
999 if((DISPCNT
& 7) > 2 && (c
< 512))
1003 if(DISPCNT
& 0x40) {
1016 int address
= 0x10000 + ((((c
+ (t
>>3) * inc
) << 5)
1017 + ((t
& 7) << 3) + ((xxx
>>3)<<6) + (xxx
& 7)) & 0x7FFF);
1021 u32 prio
= (((a2
>> 10) & 3) << 25) | ((a0
& 0x0c00)<<6);
1023 for(int xx
= 0; xx
< sizeX
; xx
++) {
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
;
1048 if(t
== 0 || t
== maskY
|| xx
== 0 || xx
== maskX
)
1049 lineOBJ
[sx
] = 0x001F;
1061 if(address
< 0x10000)
1070 if(address
> 0x17fff)
1077 int c
= (a2
& 0x3FF);
1078 if((DISPCNT
& 7) > 2 && (c
< 512))
1082 if(DISPCNT
& 0x40) {
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;
1099 for(int xx
= sizeX
- 1; xx
>= 0; xx
--) {
1105 u8 color
= vram
[address
];
1107 color
= (color
>> 4);
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
;
1128 if(t
== 0 || t
== maskY
|| xx
== 0 || xx
== maskX
)
1129 lineOBJ
[sx
] = 0x001F;
1139 if(address
< 0x10000)
1143 for(int xx
= 0; xx
< sizeX
; xx
++) {
1149 u8 color
= vram
[address
];
1151 color
= (color
>> 4);
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
;
1173 if(t
== 0 || t
== maskY
|| xx
== 0 || xx
== maskX
)
1174 lineOBJ
[sx
] = 0x001F;
1184 if(address
> 0x17fff)
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
++);
1212 // ignores non OBJ-WIN and disabled OBJ-WIN
1213 if(((a0
& 0x0c00) != 0x0800) || ((a0
& 0x0300) == 0x0200))
1216 if ((a0
& 0x0c00) == 0x0c00)
1225 int sizeX
= 8<<(a1
>>14);
1235 else if ((a0
>>14) & 2)
1243 int sy
= (a0
& 255);
1252 if((sy
+fieldY
) > 256)
1254 int t
= VCOUNT
- sy
;
1255 if((t
>= 0) && (t
< fieldY
)) {
1256 int sx
= (a1
& 0x1FF);
1258 if ((sx
+fieldX
)> 512)
1262 if((sx
< 240) || startpix
) {
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)]);
1270 int dmx
= READ16LE(&OAM
[7 + (rot
<< 4)]);
1273 int dy
= READ16LE(&OAM
[11 + (rot
<< 4)]);
1276 int dmy
= READ16LE(&OAM
[15 + (rot
<< 4)]);
1280 int realX
= ((sizeX
) << 7) - (fieldX
>> 1)*dx
- (fieldY
>>1)*dmx
1282 int realY
= ((sizeY
) << 7) - (fieldX
>> 1)*dy
- (fieldY
>>1)*dmy
1285 // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
1288 int c
= (a2
& 0x3FF);
1289 if((DISPCNT
& 7) > 2 && (c
< 512))
1296 for(int x
= 0; x
< fieldX
; x
++) {
1301 int xxx
= realX
>> 8;
1302 int yyy
= realY
>> 8;
1304 if(xxx
< 0 || xxx
>= sizeX
||
1305 yyy
< 0 || yyy
>= sizeY
||
1308 u32 color
= vram
[0x10000 + ((((c
+ (yyy
>>3) * inc
)<<5)
1309 + ((yyy
& 7)<<3) + ((xxx
>> 3)<<6) +
1310 (xxx
& 7))&0x7fff)];
1320 int c
= (a2
& 0x3FF);
1321 if((DISPCNT
& 7) > 2 && (c
< 512))
1327 // int palette = (a2 >> 8) & 0xF0;
1328 for(int x
= 0; x
< fieldX
; x
++) {
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;
1340 if(xxx
< 0 || xxx
>= sizeX
||
1341 yyy
< 0 || yyy
>= sizeY
||
1344 u32 color
= vram
[0x10000 + ((((c
+ (yyy
>>3) * inc
)<<5)
1345 + ((yyy
& 7)<<2) + ((xxx
>> 3)<<5) +
1346 ((xxx
& 7)>>1))&0x7fff)];
1365 if((sy
+sizeY
) > 256)
1367 int t
= VCOUNT
- sy
;
1368 if((t
>= 0) && (t
< sizeY
)) {
1369 int sx
= (a1
& 0x1FF);
1371 if ((sx
+sizeX
)> 512)
1375 if((sx
< 240) || startpix
) {
1380 int c
= (a2
& 0x3FF);
1381 if((DISPCNT
& 7) > 2 && (c
< 512))
1385 if(DISPCNT
& 0x40) {
1393 int address
= 0x10000 + ((((c
+ (t
>>3) * inc
) << 5)
1394 + ((t
& 7) << 3) + ((xxx
>>3)<<6) + (xxx
& 7))&0x7fff);
1397 // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
1398 for(int xx
= 0; xx
< sizeX
; xx
++) {
1404 u8 color
= vram
[address
];
1418 if(address
< 0x10000)
1427 if(address
> 0x17fff)
1434 int c
= (a2
& 0x3FF);
1435 if((DISPCNT
& 7) > 2 && (c
< 512))
1439 if(DISPCNT
& 0x40) {
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;
1451 for(int xx
= sizeX
- 1; xx
>= 0; xx
--) {
1457 u8 color
= vram
[address
];
1459 color
= (color
>> 4);
1475 if(address
< 0x10000)
1479 for(int xx
= 0; xx
< sizeX
; xx
++) {
1485 u8 color
= vram
[address
];
1487 color
= (color
>> 4);
1503 if(address
> 0x17fff)
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);
1530 color
= (color
& 0xFFFF0000) | (b
<< 10) | (g
<< 5) | r
;
1534 static inline void gfxIncreaseBrightness(u32
*line
, int coeff
)
1536 for(int x
= 0; x
< 240; x
++) {
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);
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);
1570 color
= (color
& 0xFFFF0000) | (b
<< 10) | (g
<< 5) | r
;
1575 static inline void gfxDecreaseBrightness(u32
*line
, int coeff
)
1577 for(int x
= 0; x
< 240; x
++) {
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);
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;
1617 return (color
& 0xFFFF0000) | (b
<< 10) | (g
<< 5) | r
;
1622 static inline void gfxAlphaBlend(u32
*ta
, u32
*tb
, int ca
, int cb
)
1624 for(int x
= 0; x
< 240; x
++) {
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;
1646 *ta
++ = (color
& 0xFFFF0000) | (b
<< 10) | (g
<< 5) | r
;