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 &currentX, 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