1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2 // Copyright (C) 1999-2003 Forgotten
3 // Copyright (C) 2004 Forgotten and the VBA development team
4 
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2, or(at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19 #include "GBA.h"
20 #include "Globals.h"
21 #include "Gfx.h"
22 #include "gfx-draw.h"
23 
24 namespace MDFN_IEN_GBA
25 {
26 
mode0RenderLine()27 void mode0RenderLine()
28 {
29   uint16 *palette = (uint16 *)paletteRAM;
30 
31   if(DISPCNT & 0x80) {
32     for(int x = 0; x < 240; x++) {
33       lineMix[x] = 0x7fff;
34     }
35     return;
36   }
37 
38   if(layerEnable & 0x0100) {
39     gfxDrawTextScreen(BG0CNT, BGHOFS[0], BGVOFS[0], line0);
40   }
41 
42   if(layerEnable & 0x0200) {
43     gfxDrawTextScreen(BG1CNT, BGHOFS[1], BGVOFS[1], line1);
44   }
45 
46   if(layerEnable & 0x0400) {
47     gfxDrawTextScreen(BG2CNT, BGHOFS[2], BGVOFS[2], line2);
48   }
49 
50   if(layerEnable & 0x0800) {
51     gfxDrawTextScreen(BG3CNT, BGHOFS[3], BGVOFS[3], line3);
52   }
53 
54   gfxDrawSprites();
55 
56   uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
57 
58   for(int x = 0; x < 240; x++) {
59     uint32 color = backdrop;
60     uint8 top = 0x20;
61 
62     if(line0[x] < color) {
63       color = line0[x];
64       top = 0x01;
65     }
66 
67     if(line1[x] < (color & 0xFF000000)) {
68       color = line1[x];
69       top = 0x02;
70     }
71 
72     if(line2[x] < (color & 0xFF000000)) {
73       color = line2[x];
74       top = 0x04;
75     }
76 
77     if(line3[x] < (color & 0xFF000000)) {
78       color = line3[x];
79       top = 0x08;
80     }
81 
82     if(lineOBJ[x] < (color & 0xFF000000)) {
83       color = lineOBJ[x];
84       top = 0x10;
85     }
86 
87     if((top & 0x10) && (color & 0x00010000)) {
88       // semi-transparent OBJ
89       uint32 back = backdrop;
90       uint8 top2 = 0x20;
91 
92       if(line0[x] < (back & 0xFF000000)) {
93         back = line0[x];
94         top2 = 0x01;
95       }
96 
97       if(line1[x] < (back & 0xFF000000)) {
98         back = line1[x];
99         top2 = 0x02;
100       }
101 
102       if(line2[x] < (back & 0xFF000000)) {
103         back = line2[x];
104         top2 = 0x04;
105       }
106 
107       if(line3[x] < (back & 0xFF000000)) {
108         back = line3[x];
109         top2 = 0x08;
110       }
111 
112       if(top2 & (BLDMOD>>8))
113         color = gfxAlphaBlend(color, back,
114                               all_coeff[COLEV & 0x1F],
115                               all_coeff[(COLEV >> 8) & 0x1F]);
116         else {
117           switch((BLDMOD >> 6) & 3) {
118           case 2:
119             if(BLDMOD & top)
120               color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]);
121             break;
122           case 3:
123             if(BLDMOD & top)
124               color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]);
125             break;
126           }
127         }
128     }
129 
130     lineMix[x] = color;
131   }
132 }
133 
mode0RenderLineNoWindow()134 void mode0RenderLineNoWindow()
135 {
136   uint16 *palette = (uint16 *)paletteRAM;
137 
138   if(DISPCNT & 0x80) {
139     for(int x = 0; x < 240; x++) {
140       lineMix[x] = 0x7fff;
141     }
142     return;
143   }
144 
145   if(layerEnable & 0x0100) {
146     gfxDrawTextScreen(BG0CNT, BGHOFS[0], BGVOFS[0], line0);
147   }
148 
149   if(layerEnable & 0x0200) {
150     gfxDrawTextScreen(BG1CNT, BGHOFS[1], BGVOFS[1], line1);
151   }
152 
153   if(layerEnable & 0x0400) {
154     gfxDrawTextScreen(BG2CNT, BGHOFS[2], BGVOFS[2], line2);
155   }
156 
157   if(layerEnable & 0x0800) {
158     gfxDrawTextScreen(BG3CNT, BGHOFS[3], BGVOFS[3], line3);
159   }
160 
161   gfxDrawSprites();
162 
163   uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
164 
165   int effect = (BLDMOD >> 6) & 3;
166 
167   for(int x = 0; x < 240; x++) {
168     uint32 color = backdrop;
169     uint8 top = 0x20;
170 
171     if(line0[x] < color) {
172       color = line0[x];
173       top = 0x01;
174     }
175 
176     if(line1[x] < (color & 0xFF000000)) {
177       color = line1[x];
178       top = 0x02;
179     }
180 
181     if(line2[x] < (color & 0xFF000000)) {
182       color = line2[x];
183       top = 0x04;
184     }
185 
186     if(line3[x] < (color & 0xFF000000)) {
187       color = line3[x];
188       top = 0x08;
189     }
190 
191     if(lineOBJ[x] < (color & 0xFF000000)) {
192       color = lineOBJ[x];
193       top = 0x10;
194     }
195 
196     if(!(color & 0x00010000)) {
197       switch(effect) {
198       case 0:
199         break;
200       case 1:
201         {
202           if(top & BLDMOD) {
203             uint32 back = backdrop;
204             uint8 top2 = 0x20;
205             if(line0[x] < back) {
206               if(top != 0x01) {
207                 back = line0[x];
208                 top2 = 0x01;
209               }
210             }
211 
212             if(line1[x] < (back & 0xFF000000)) {
213               if(top != 0x02) {
214                 back = line1[x];
215                 top2 = 0x02;
216               }
217             }
218 
219             if(line2[x] < (back & 0xFF000000)) {
220               if(top != 0x04) {
221                 back = line2[x];
222                 top2 = 0x04;
223               }
224             }
225 
226             if(line3[x] < (back & 0xFF000000)) {
227               if(top != 0x08) {
228                 back = line3[x];
229                 top2 = 0x08;
230               }
231             }
232 
233             if(lineOBJ[x] < (back & 0xFF000000)) {
234               if(top != 0x10) {
235                 back = lineOBJ[x];
236                 top2 = 0x10;
237               }
238             }
239 
240             if(top2 & (BLDMOD>>8))
241               color = gfxAlphaBlend(color, back,
242                                     all_coeff[COLEV & 0x1F],
243                                     all_coeff[(COLEV >> 8) & 0x1F]);
244 
245           }
246         }
247         break;
248       case 2:
249         if(BLDMOD & top)
250           color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]);
251         break;
252       case 3:
253         if(BLDMOD & top)
254           color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]);
255         break;
256       }
257     } else {
258       // semi-transparent OBJ
259       uint32 back = backdrop;
260       uint8 top2 = 0x20;
261 
262       if(line0[x] < back) {
263         back = line0[x];
264         top2 = 0x01;
265       }
266 
267       if(line1[x] < (back & 0xFF000000)) {
268         back = line1[x];
269         top2 = 0x02;
270       }
271 
272       if(line2[x] < (back & 0xFF000000)) {
273         back = line2[x];
274         top2 = 0x04;
275       }
276 
277       if(line3[x] < (back & 0xFF000000)) {
278         back = line3[x];
279         top2 = 0x08;
280       }
281 
282       if(top2 & (BLDMOD>>8))
283         color = gfxAlphaBlend(color, back,
284                               all_coeff[COLEV & 0x1F],
285                               all_coeff[(COLEV >> 8) & 0x1F]);
286       else {
287         switch((BLDMOD >> 6) & 3) {
288         case 2:
289           if(BLDMOD & top)
290             color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]);
291           break;
292         case 3:
293           if(BLDMOD & top)
294             color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]);
295           break;
296         }
297       }
298     }
299 
300     lineMix[x] = color;
301   }
302 }
303 
mode0RenderLineAll()304 void mode0RenderLineAll()
305 {
306   uint16 *palette = (uint16 *)paletteRAM;
307 
308   if(DISPCNT & 0x80) {
309     for(int x = 0; x < 240; x++) {
310       lineMix[x] = 0x7fff;
311     }
312     return;
313   }
314 
315   bool inWindow0 = false;
316   bool inWindow1 = false;
317 
318   if(layerEnable & 0x2000) {
319     uint8 v0 = WIN0V >> 8;
320     uint8 v1 = WIN0V & 255;
321     inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
322     if(v1 >= v0)
323       inWindow0 |= (VCOUNT >= v0 && VCOUNT < v1);
324     else
325       inWindow0 |= (VCOUNT >= v0 || VCOUNT < v1);
326   }
327   if(layerEnable & 0x4000) {
328     uint8 v0 = WIN1V >> 8;
329     uint8 v1 = WIN1V & 255;
330     inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
331     if(v1 >= v0)
332       inWindow1 |= (VCOUNT >= v0 && VCOUNT < v1);
333     else
334       inWindow1 |= (VCOUNT >= v0 || VCOUNT < v1);
335   }
336 
337   if((layerEnable & 0x0100)) {
338     gfxDrawTextScreen(BG0CNT, BGHOFS[0], BGVOFS[0], line0);
339   }
340 
341   if((layerEnable & 0x0200)) {
342     gfxDrawTextScreen(BG1CNT, BGHOFS[1], BGVOFS[1], line1);
343   }
344 
345   if((layerEnable & 0x0400)) {
346     gfxDrawTextScreen(BG2CNT, BGHOFS[2], BGVOFS[2], line2);
347   }
348 
349   if((layerEnable & 0x0800)) {
350     gfxDrawTextScreen(BG3CNT, BGHOFS[3], BGVOFS[3], line3);
351   }
352 
353   gfxDrawSprites();
354   gfxDrawOBJWin();
355 
356   uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
357 
358   uint8 inWin0Mask = WININ & 0xFF;
359   uint8 inWin1Mask = WININ >> 8;
360   uint8 outMask = WINOUT & 0xFF;
361 
362   for(int x = 0; x < 240; x++) {
363     uint32 color = backdrop;
364     uint8 top = 0x20;
365     uint8 mask = outMask;
366 
367     if(!(lineOBJWin[x] & 0x80000000)) {
368       mask = WINOUT >> 8;
369     }
370 
371     if(inWindow1) {
372       if(gfxInWin1[x])
373         mask = inWin1Mask;
374     }
375 
376     if(inWindow0) {
377       if(gfxInWin0[x]) {
378         mask = inWin0Mask;
379       }
380     }
381 
382     if((mask & 1) && (line0[x] < color)) {
383       color = line0[x];
384       top = 0x01;
385     }
386 
387     if((mask & 2) && (line1[x] < (color & 0xFF000000))) {
388       color = line1[x];
389       top = 0x02;
390     }
391 
392     if((mask & 4) && (line2[x] < (color & 0xFF000000))) {
393       color = line2[x];
394       top = 0x04;
395     }
396 
397     if((mask & 8) && (line3[x] < (color & 0xFF000000))) {
398       color = line3[x];
399       top = 0x08;
400     }
401 
402     if((mask & 16) && (lineOBJ[x] < (color & 0xFF000000))) {
403       color = lineOBJ[x];
404       top = 0x10;
405     }
406 
407     // special FX on in the window
408     if(mask & 32) {
409       if(!(color & 0x00010000)) {
410         switch((BLDMOD >> 6) & 3) {
411         case 0:
412           break;
413         case 1:
414           {
415             if(top & BLDMOD) {
416               uint32 back = backdrop;
417               uint8 top2 = 0x20;
418               if((mask & 1) && line0[x] < (back & 0xFF000000)) {
419                 if(top != 0x01) {
420                   back = line0[x];
421                   top2 = 0x01;
422                 }
423               }
424 
425               if((mask & 2) && line1[x] < (back & 0xFF000000)) {
426                 if(top != 0x02) {
427                   back = line1[x];
428                   top2 = 0x02;
429                 }
430               }
431 
432               if((mask & 4) && line2[x] < (back & 0xFF000000)) {
433                 if(top != 0x04) {
434                   back = line2[x];
435                   top2 = 0x04;
436                 }
437               }
438 
439               if((mask & 8) && line3[x] < (back & 0xFF000000)) {
440                 if(top != 0x08) {
441                   back = line3[x];
442                   top2 = 0x08;
443                 }
444               }
445 
446               if((mask & 16) && lineOBJ[x] < (back & 0xFF000000)) {
447                 if(top != 0x10) {
448                   back = lineOBJ[x];
449                   top2 = 0x10;
450                 }
451               }
452 
453               if(top2 & (BLDMOD>>8))
454                 color = gfxAlphaBlend(color, back,
455                 all_coeff[COLEV & 0x1F],
456                 all_coeff[(COLEV >> 8) & 0x1F]);
457             }
458           }
459           break;
460         case 2:
461           if(BLDMOD & top)
462             color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]);
463           break;
464         case 3:
465           if(BLDMOD & top)
466             color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]);
467           break;
468         }
469       } else {
470         // semi-transparent OBJ
471         uint32 back = backdrop;
472         uint8 top2 = 0x20;
473 
474         if((mask & 1) && (line0[x] < (back & 0xFF000000))) {
475           back = line0[x];
476           top2 = 0x01;
477         }
478 
479         if((mask & 2) && (line1[x] < (back & 0xFF000000))) {
480           back = line1[x];
481           top2 = 0x02;
482         }
483 
484         if((mask & 4) && (line2[x] < (back & 0xFF000000))) {
485           back = line2[x];
486           top2 = 0x04;
487         }
488 
489         if((mask & 8) && (line3[x] < (back & 0xFF000000))) {
490           back = line3[x];
491           top2 = 0x08;
492         }
493 
494         if(top2 & (BLDMOD>>8))
495           color = gfxAlphaBlend(color, back,
496           all_coeff[COLEV & 0x1F],
497           all_coeff[(COLEV >> 8) & 0x1F]);
498         else {
499           switch((BLDMOD >> 6) & 3) {
500           case 2:
501             if(BLDMOD & top)
502               color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]);
503             break;
504           case 3:
505             if(BLDMOD & top)
506               color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]);
507             break;
508           }
509         }
510       }
511     } else if(color & 0x00010000) {
512       // semi-transparent OBJ
513       uint32 back = backdrop;
514       uint8 top2 = 0x20;
515 
516       if((mask & 1) && (line0[x] < (back & 0xFF000000))) {
517         back = line0[x];
518         top2 = 0x01;
519       }
520 
521       if((mask & 2) && (line1[x] < (back & 0xFF000000))) {
522         back = line1[x];
523         top2 = 0x02;
524       }
525 
526       if((mask & 4) && (line2[x] < (back & 0xFF000000))) {
527         back = line2[x];
528         top2 = 0x04;
529       }
530 
531       if((mask & 8) && (line3[x] < (back & 0xFF000000))) {
532         back = line3[x];
533         top2 = 0x08;
534       }
535 
536       if(top2 & (BLDMOD>>8))
537         color = gfxAlphaBlend(color, back,
538         all_coeff[COLEV & 0x1F],
539         all_coeff[(COLEV >> 8) & 0x1F]);
540       else {
541         switch((BLDMOD >> 6) & 3) {
542         case 2:
543           if(BLDMOD & top)
544             color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]);
545           break;
546         case 3:
547           if(BLDMOD & top)
548             color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]);
549           break;
550         }
551       }
552     }
553 
554     lineMix[x] = color;
555   }
556 }
557 
558 }
559