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 
mode2RenderLine()27 void mode2RenderLine()
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     gfxLastVCOUNT = VCOUNT;
36     return;
37   }
38 
39   if(layerEnable & 0x0400) {
40     int changed = gfxBG2Changed;
41     if(gfxLastVCOUNT > VCOUNT)
42       changed = 3;
43 
44     gfxDrawRotScreen(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
45                      BG2PA, BG2PB, BG2PC, BG2PD, gfxBG2X, gfxBG2Y,
46                      changed, line2);
47   }
48 
49   if(layerEnable & 0x0800) {
50     int changed = gfxBG3Changed;
51     if(gfxLastVCOUNT > VCOUNT)
52       changed = 3;
53 
54     gfxDrawRotScreen(BG3CNT, BG3X_L, BG3X_H, BG3Y_L, BG3Y_H,
55                      BG3PA, BG3PB, BG3PC, BG3PD, gfxBG3X, gfxBG3Y,
56                      changed, line3);
57   }
58 
59   gfxDrawSprites();
60 
61   uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
62 
63   for(int x = 0; x < 240; x++) {
64     uint32 color = backdrop;
65     uint8 top = 0x20;
66 
67 
68     if(line2[x] < (color & 0xFF000000)) {
69       color = line2[x];
70       top = 0x04;
71     }
72 
73     if(line3[x] < (color & 0xFF000000)) {
74       color = line3[x];
75       top = 0x08;
76     }
77 
78     if(lineOBJ[x] < (color & 0xFF000000)) {
79       color = lineOBJ[x];
80       top = 0x10;
81     }
82 
83     if((top & 0x10) && (color & 0x00010000)) {
84       // semi-transparent OBJ
85       uint32 back = backdrop;
86       uint8 top2 = 0x20;
87 
88       if(line2[x] < (back & 0xFF000000)) {
89         back = line2[x];
90         top2 = 0x04;
91       }
92 
93       if(line3[x] < (back & 0xFF000000)) {
94         back = line3[x];
95         top2 = 0x08;
96       }
97 
98       if(top2 & (BLDMOD>>8))
99         color = gfxAlphaBlend(color, back,
100                               all_coeff[COLEV & 0x1F],
101                               all_coeff[(COLEV >> 8) & 0x1F]);
102       else {
103         switch((BLDMOD >> 6) & 3) {
104         case 2:
105           if(BLDMOD & top)
106             color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]);
107           break;
108         case 3:
109           if(BLDMOD & top)
110             color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]);
111           break;
112         }
113       }
114     }
115 
116     lineMix[x] = color;
117   }
118   gfxBG2Changed = 0;
119   gfxBG3Changed = 0;
120   gfxLastVCOUNT = VCOUNT;
121 }
122 
mode2RenderLineNoWindow()123 void mode2RenderLineNoWindow()
124 {
125   uint16 *palette = (uint16 *)paletteRAM;
126 
127   if(DISPCNT & 0x80) {
128     for(int x = 0; x < 240; x++) {
129       lineMix[x] = 0x7fff;
130     }
131     gfxLastVCOUNT = VCOUNT;
132     return;
133   }
134 
135   if(layerEnable & 0x0400) {
136     int changed = gfxBG2Changed;
137     if(gfxLastVCOUNT > VCOUNT)
138       changed = 3;
139 
140     gfxDrawRotScreen(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
141                      BG2PA, BG2PB, BG2PC, BG2PD, gfxBG2X, gfxBG2Y,
142                      changed, line2);
143   }
144 
145   if(layerEnable & 0x0800) {
146     int changed = gfxBG3Changed;
147     if(gfxLastVCOUNT > VCOUNT)
148       changed = 3;
149 
150     gfxDrawRotScreen(BG3CNT, BG3X_L, BG3X_H, BG3Y_L, BG3Y_H,
151                      BG3PA, BG3PB, BG3PC, BG3PD, gfxBG3X, gfxBG3Y,
152                      changed, line3);
153   }
154 
155   gfxDrawSprites();
156 
157   uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
158 
159   for(int x = 0; x < 240; x++) {
160     uint32 color = backdrop;
161     uint8 top = 0x20;
162 
163 
164     if(line2[x] < (color & 0xFF000000)) {
165       color = line2[x];
166       top = 0x04;
167     }
168 
169     if(line3[x] < (color & 0xFF000000)) {
170       color = line3[x];
171       top = 0x08;
172     }
173 
174     if(lineOBJ[x] < (color & 0xFF000000)) {
175       color = lineOBJ[x];
176       top = 0x10;
177     }
178 
179     if(!(color & 0x00010000)) {
180       switch((BLDMOD >> 6) & 3) {
181       case 0:
182         break;
183       case 1:
184         {
185           if(top & BLDMOD) {
186             uint32 back = backdrop;
187             uint8 top2 = 0x20;
188 
189             if(line2[x] < (back & 0xFF000000)) {
190               if(top != 0x04) {
191                 back = line2[x];
192                 top2 = 0x04;
193               }
194             }
195 
196             if(line3[x] < (back & 0xFF000000)) {
197               if(top != 0x08) {
198                 back = line3[x];
199                 top2 = 0x08;
200               }
201             }
202 
203             if(lineOBJ[x] < (back & 0xFF000000)) {
204               if(top != 0x10) {
205                 back = lineOBJ[x];
206                 top2 = 0x10;
207               }
208             }
209 
210             if(top2 & (BLDMOD>>8))
211               color = gfxAlphaBlend(color, back,
212                                     all_coeff[COLEV & 0x1F],
213                                     all_coeff[(COLEV >> 8) & 0x1F]);
214           }
215         }
216         break;
217       case 2:
218         if(BLDMOD & top)
219           color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]);
220         break;
221       case 3:
222         if(BLDMOD & top)
223           color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]);
224         break;
225       }
226     } else {
227       // semi-transparent OBJ
228       uint32 back = backdrop;
229       uint8 top2 = 0x20;
230 
231       if(line2[x] < (back & 0xFF000000)) {
232         back = line2[x];
233         top2 = 0x04;
234       }
235 
236       if(line3[x] < (back & 0xFF000000)) {
237         back = line3[x];
238         top2 = 0x08;
239       }
240 
241       if(top2 & (BLDMOD>>8))
242         color = gfxAlphaBlend(color, back,
243                               all_coeff[COLEV & 0x1F],
244                               all_coeff[(COLEV >> 8) & 0x1F]);
245       else {
246         switch((BLDMOD >> 6) & 3) {
247         case 2:
248           if(BLDMOD & top)
249             color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]);
250           break;
251         case 3:
252           if(BLDMOD & top)
253             color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]);
254           break;
255         }
256       }
257     }
258 
259     lineMix[x] = color;
260   }
261   gfxBG2Changed = 0;
262   gfxBG3Changed = 0;
263   gfxLastVCOUNT = VCOUNT;
264 }
265 
mode2RenderLineAll()266 void mode2RenderLineAll()
267 {
268   uint16 *palette = (uint16 *)paletteRAM;
269 
270   if(DISPCNT & 0x80) {
271     for(int x = 0; x < 240; x++) {
272       lineMix[x] = 0x7fff;
273     }
274     gfxLastVCOUNT = VCOUNT;
275     return;
276   }
277 
278   bool inWindow0 = false;
279   bool inWindow1 = false;
280 
281   if(layerEnable & 0x2000) {
282     uint8 v0 = WIN0V >> 8;
283     uint8 v1 = WIN0V & 255;
284     inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
285     if(v1 >= v0)
286       inWindow0 |= (VCOUNT >= v0 && VCOUNT < v1);
287     else
288       inWindow0 |= (VCOUNT >= v0 || VCOUNT < v1);
289   }
290   if(layerEnable & 0x4000) {
291     uint8 v0 = WIN1V >> 8;
292     uint8 v1 = WIN1V & 255;
293     inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
294     if(v1 >= v0)
295       inWindow1 |= (VCOUNT >= v0 && VCOUNT < v1);
296     else
297       inWindow1 |= (VCOUNT >= v0 || VCOUNT < v1);
298   }
299 
300   if(layerEnable & 0x0400) {
301     int changed = gfxBG2Changed;
302     if(gfxLastVCOUNT > VCOUNT)
303       changed = 3;
304 
305     gfxDrawRotScreen(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
306                      BG2PA, BG2PB, BG2PC, BG2PD, gfxBG2X, gfxBG2Y,
307                      changed, line2);
308   }
309 
310   if(layerEnable & 0x0800) {
311     int changed = gfxBG3Changed;
312     if(gfxLastVCOUNT > VCOUNT)
313       changed = 3;
314 
315     gfxDrawRotScreen(BG3CNT, BG3X_L, BG3X_H, BG3Y_L, BG3Y_H,
316                      BG3PA, BG3PB, BG3PC, BG3PD, gfxBG3X, gfxBG3Y,
317                      changed, line3);
318   }
319 
320   gfxDrawSprites();
321   gfxDrawOBJWin();
322 
323   uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000);
324 
325   uint8 inWin0Mask = WININ & 0xFF;
326   uint8 inWin1Mask = WININ >> 8;
327   uint8 outMask = WINOUT & 0xFF;
328 
329   for(int x = 0; x < 240; x++) {
330     uint32 color = backdrop;
331     uint8 top = 0x20;
332     uint8 mask = outMask;
333 
334     if(!(lineOBJWin[x] & 0x80000000)) {
335       mask = WINOUT >> 8;
336     }
337 
338     if(inWindow1) {
339       if(gfxInWin1[x])
340         mask = inWin1Mask;
341     }
342 
343     if(inWindow0) {
344       if(gfxInWin0[x]) {
345         mask = inWin0Mask;
346       }
347     }
348 
349     if(line2[x] < color && (mask & 4)) {
350       color = line2[x];
351       top = 0x04;
352     }
353 
354     if(line3[x] < (color & 0xFF000000) && (mask & 8)) {
355       color = line3[x];
356       top = 0x08;
357     }
358 
359     if(lineOBJ[x] < (color & 0xFF000000) && (mask & 16)) {
360       color = lineOBJ[x];
361       top = 0x10;
362     }
363 
364     if(mask & 32) {
365       if(!(color & 0x00010000)) {
366         switch((BLDMOD >> 6) & 3) {
367         case 0:
368           break;
369         case 1:
370           {
371             if(top & BLDMOD) {
372               uint32 back = backdrop;
373               uint8 top2 = 0x20;
374 
375               if((mask & 4) && line2[x] < back) {
376                 if(top != 0x04) {
377                   back = line2[x];
378                   top2 = 0x04;
379                 }
380               }
381 
382               if((mask & 8) && line3[x] < (back & 0xFF000000)) {
383                 if(top != 0x08) {
384                   back = line3[x];
385                   top2 = 0x08;
386                 }
387               }
388 
389               if((mask & 16) && lineOBJ[x] < (back & 0xFF000000)) {
390                 if(top != 0x10) {
391                   back = lineOBJ[x];
392                   top2 = 0x10;
393                 }
394               }
395 
396               if(top2 & (BLDMOD>>8))
397                 color = gfxAlphaBlend(color, back,
398                 all_coeff[COLEV & 0x1F],
399                 all_coeff[(COLEV >> 8) & 0x1F]);
400             }
401           }
402           break;
403         case 2:
404           if(BLDMOD & top)
405             color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]);
406           break;
407         case 3:
408           if(BLDMOD & top)
409             color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]);
410           break;
411         }
412       } else {
413         // semi-transparent OBJ
414         uint32 back = backdrop;
415         uint8 top2 = 0x20;
416 
417         if((mask & 4) && line2[x] < back) {
418           back = line2[x];
419           top2 = 0x04;
420         }
421 
422         if((mask & 8) && line3[x] < (back & 0xFF000000)) {
423           back = line3[x];
424           top2 = 0x08;
425         }
426 
427         if(top2 & (BLDMOD>>8))
428           color = gfxAlphaBlend(color, back,
429           all_coeff[COLEV & 0x1F],
430           all_coeff[(COLEV >> 8) & 0x1F]);
431         else {
432           switch((BLDMOD >> 6) & 3) {
433           case 2:
434             if(BLDMOD & top)
435               color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]);
436             break;
437           case 3:
438             if(BLDMOD & top)
439               color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]);
440             break;
441           }
442         }
443       }
444     } else if(color & 0x00010000) {
445       // semi-transparent OBJ
446       uint32 back = backdrop;
447       uint8 top2 = 0x20;
448 
449       if((mask & 4) && line2[x] < back) {
450         back = line2[x];
451         top2 = 0x04;
452       }
453 
454       if((mask & 8) && line3[x] < (back & 0xFF000000)) {
455         back = line3[x];
456         top2 = 0x08;
457       }
458 
459       if(top2 & (BLDMOD>>8))
460         color = gfxAlphaBlend(color, back,
461         all_coeff[COLEV & 0x1F],
462         all_coeff[(COLEV >> 8) & 0x1F]);
463       else {
464         switch((BLDMOD >> 6) & 3) {
465         case 2:
466           if(BLDMOD & top)
467             color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]);
468           break;
469         case 3:
470           if(BLDMOD & top)
471             color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]);
472           break;
473         }
474       }
475     }
476 
477     lineMix[x] = color;
478   }
479   gfxBG2Changed = 0;
480   gfxBG3Changed = 0;
481   gfxLastVCOUNT = VCOUNT;
482 }
483 
484 }
485