1 #include "GBA.h"
2 #include "Globals.h"
3 #include "GBAGfx.h"
4 
mode5RenderLine()5 void mode5RenderLine()
6 {
7   if(DISPCNT & 0x0080) {
8     for(int x = 0; x < 240; x++) {
9       lineMix[x] = 0x7fff;
10     }
11     gfxLastVCOUNT = VCOUNT;
12     return;
13   }
14 
15   u16 *palette = (u16 *)paletteRAM;
16 
17   if(layerEnable & 0x0400) {
18     int changed = gfxBG2Changed;
19 
20     if(gfxLastVCOUNT > VCOUNT)
21       changed = 3;
22 
23     gfxDrawRotScreen16Bit160(BG2CNT, BG2X_L, BG2X_H,
24                              BG2Y_L, BG2Y_H, BG2PA, BG2PB,
25                              BG2PC, BG2PD,
26                              gfxBG2X, gfxBG2Y, changed,
27                              line2);
28   }
29 
30   gfxDrawSprites(lineOBJ);
31 
32   u32 background;
33   if(customBackdropColor == -1) {
34     background = (READ16LE(&palette[0]) | 0x30000000);
35   } else {
36     background = ((customBackdropColor & 0x7FFF) | 0x30000000);
37   }
38 
39   for(int x = 0; x < 240; x++) {
40     u32 color = background;
41     u8 top = 0x20;
42 
43     if(line2[x] < color) {
44       color = line2[x];
45       top = 0x04;
46     }
47 
48     if((u8)(lineOBJ[x]>>24) < (u8)(color >>24)) {
49       color = lineOBJ[x];
50       top = 0x10;
51     }
52 
53     if((top & 0x10) && (color & 0x00010000)) {
54       // semi-transparent OBJ
55       u32 back = background;
56       u8 top2 = 0x20;
57 
58       if(line2[x] < back) {
59         back = line2[x];
60         top2 = 0x04;
61       }
62 
63       if(top2 & (BLDMOD>>8))
64         color = gfxAlphaBlend(color, back,
65                               coeff[COLEV & 0x1F],
66                               coeff[(COLEV >> 8) & 0x1F]);
67       else {
68         switch((BLDMOD >> 6) & 3) {
69         case 2:
70           if(BLDMOD & top)
71             color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
72           break;
73         case 3:
74           if(BLDMOD & top)
75             color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
76           break;
77         }
78       }
79     }
80 
81     lineMix[x] = color;
82   }
83   gfxBG2Changed = 0;
84   gfxLastVCOUNT = VCOUNT;
85 }
86 
mode5RenderLineNoWindow()87 void mode5RenderLineNoWindow()
88 {
89   if(DISPCNT & 0x0080) {
90     for(int x = 0; x < 240; x++) {
91       lineMix[x] = 0x7fff;
92     }
93     gfxLastVCOUNT = VCOUNT;
94     return;
95   }
96 
97   u16 *palette = (u16 *)paletteRAM;
98 
99   if(layerEnable & 0x0400) {
100     int changed = gfxBG2Changed;
101 
102     if(gfxLastVCOUNT > VCOUNT)
103       changed = 3;
104 
105     gfxDrawRotScreen16Bit160(BG2CNT, BG2X_L, BG2X_H,
106                              BG2Y_L, BG2Y_H, BG2PA, BG2PB,
107                              BG2PC, BG2PD,
108                              gfxBG2X, gfxBG2Y, changed,
109                              line2);
110   }
111 
112   gfxDrawSprites(lineOBJ);
113 
114   u32 background;
115   if(customBackdropColor == -1) {
116     background = (READ16LE(&palette[0]) | 0x30000000);
117   } else {
118     background = ((customBackdropColor & 0x7FFF) | 0x30000000);
119   }
120 
121   for(int x = 0; x < 240; x++) {
122     u32 color = background;
123     u8 top = 0x20;
124 
125     if(line2[x] < color) {
126       color = line2[x];
127       top = 0x04;
128     }
129 
130     if((u8)(lineOBJ[x]>>24) < (u8)(color >>24)) {
131       color = lineOBJ[x];
132       top = 0x10;
133     }
134 
135     if(!(color & 0x00010000)) {
136       switch((BLDMOD >> 6) & 3) {
137       case 0:
138         break;
139       case 1:
140         {
141           if(top & BLDMOD) {
142             u32 back = background;
143             u8 top2 = 0x20;
144 
145             if(line2[x] < back) {
146               if(top != 0x04) {
147                 back = line2[x];
148                 top2 = 0x04;
149               }
150             }
151 
152             if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
153               if(top != 0x10) {
154                 back = lineOBJ[x];
155                 top2 = 0x10;
156               }
157             }
158 
159             if(top2 & (BLDMOD>>8))
160               color = gfxAlphaBlend(color, back,
161                                     coeff[COLEV & 0x1F],
162                                     coeff[(COLEV >> 8) & 0x1F]);
163 
164           }
165         }
166         break;
167       case 2:
168         if(BLDMOD & top)
169           color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
170         break;
171       case 3:
172         if(BLDMOD & top)
173           color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
174         break;
175       }
176     } else {
177       // semi-transparent OBJ
178       u32 back = background;
179       u8 top2 = 0x20;
180 
181       if(line2[x] < back) {
182         back = line2[x];
183         top2 = 0x04;
184       }
185 
186       if(top2 & (BLDMOD>>8))
187         color = gfxAlphaBlend(color, back,
188                               coeff[COLEV & 0x1F],
189                               coeff[(COLEV >> 8) & 0x1F]);
190       else {
191         switch((BLDMOD >> 6) & 3) {
192         case 2:
193           if(BLDMOD & top)
194             color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
195           break;
196         case 3:
197           if(BLDMOD & top)
198             color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
199           break;
200         }
201       }
202     }
203 
204     lineMix[x] = color;
205   }
206   gfxBG2Changed = 0;
207   gfxLastVCOUNT = VCOUNT;
208 }
209 
mode5RenderLineAll()210 void mode5RenderLineAll()
211 {
212   if(DISPCNT & 0x0080) {
213     for(int x = 0; x < 240; x++) {
214       lineMix[x] = 0x7fff;
215     }
216     gfxLastVCOUNT = VCOUNT;
217     return;
218   }
219 
220   u16 *palette = (u16 *)paletteRAM;
221 
222   if(layerEnable & 0x0400) {
223     int changed = gfxBG2Changed;
224 
225     if(gfxLastVCOUNT > VCOUNT)
226       changed = 3;
227 
228     gfxDrawRotScreen16Bit160(BG2CNT, BG2X_L, BG2X_H,
229                              BG2Y_L, BG2Y_H, BG2PA, BG2PB,
230                              BG2PC, BG2PD,
231                              gfxBG2X, gfxBG2Y, changed,
232                              line2);
233   }
234 
235   gfxDrawSprites(lineOBJ);
236   gfxDrawOBJWin(lineOBJWin);
237 
238   bool inWindow0 = false;
239   bool inWindow1 = false;
240 
241   if(layerEnable & 0x2000) {
242     u8 v0 = WIN0V >> 8;
243     u8 v1 = WIN0V & 255;
244     inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
245     if(v1 >= v0)
246       inWindow0 |= (VCOUNT >= v0 && VCOUNT < v1);
247     else
248       inWindow0 |= (VCOUNT >= v0 || VCOUNT < v1);
249   }
250   if(layerEnable & 0x4000) {
251     u8 v0 = WIN1V >> 8;
252     u8 v1 = WIN1V & 255;
253     inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
254     if(v1 >= v0)
255       inWindow1 |= (VCOUNT >= v0 && VCOUNT < v1);
256     else
257       inWindow1 |= (VCOUNT >= v0 || VCOUNT < v1);
258   }
259 
260   u8 inWin0Mask = WININ & 0xFF;
261   u8 inWin1Mask = WININ >> 8;
262   u8 outMask = WINOUT & 0xFF;
263 
264   u32 background;
265   if(customBackdropColor == -1) {
266     background = (READ16LE(&palette[0]) | 0x30000000);
267   } else {
268     background = ((customBackdropColor & 0x7FFF) | 0x30000000);
269   }
270 
271   for(int x = 0; x < 240; x++) {
272     u32 color = background;
273     u8 top = 0x20;
274     u8 mask = outMask;
275 
276     if(!(lineOBJWin[x] & 0x80000000)) {
277       mask = WINOUT >> 8;
278     }
279 
280     if(inWindow1) {
281       if(gfxInWin1[x])
282         mask = inWin1Mask;
283     }
284 
285     if(inWindow0) {
286       if(gfxInWin0[x]) {
287         mask = inWin0Mask;
288       }
289     }
290 
291     if((mask & 4) && (line2[x] < color)) {
292       color = line2[x];
293       top = 0x04;
294     }
295 
296     if((mask & 16) && ((u8)(lineOBJ[x]>>24) < (u8)(color >>24))) {
297       color = lineOBJ[x];
298       top = 0x10;
299     }
300 
301     if(color & 0x00010000) {
302       // semi-transparent OBJ
303       u32 back = background;
304       u8 top2 = 0x20;
305 
306       if((mask & 4) && line2[x] < back) {
307         back = line2[x];
308         top2 = 0x04;
309       }
310 
311       if(top2 & (BLDMOD>>8))
312         color = gfxAlphaBlend(color, back,
313                               coeff[COLEV & 0x1F],
314                               coeff[(COLEV >> 8) & 0x1F]);
315       else {
316         switch((BLDMOD >> 6) & 3) {
317         case 2:
318           if(BLDMOD & top)
319             color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
320           break;
321         case 3:
322           if(BLDMOD & top)
323             color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
324           break;
325         }
326       }
327     } else if(mask & 32) {
328       switch((BLDMOD >> 6) & 3) {
329       case 0:
330         break;
331       case 1:
332         {
333           if(top & BLDMOD) {
334             u32 back = background;
335             u8 top2 = 0x20;
336 
337             if((mask & 4) && line2[x] < back) {
338               if(top != 0x04) {
339                 back = line2[x];
340                 top2 = 0x04;
341               }
342             }
343 
344             if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
345               if(top != 0x10) {
346                 back = lineOBJ[x];
347                 top2 = 0x10;
348               }
349             }
350 
351             if(top2 & (BLDMOD>>8))
352               color = gfxAlphaBlend(color, back,
353                                     coeff[COLEV & 0x1F],
354                                     coeff[(COLEV >> 8) & 0x1F]);
355 
356           }
357         }
358         break;
359       case 2:
360         if(BLDMOD & top)
361           color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
362         break;
363       case 3:
364         if(BLDMOD & top)
365           color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
366         break;
367       }
368     }
369 
370     lineMix[x] = color;
371   }
372   gfxBG2Changed = 0;
373   gfxLastVCOUNT = VCOUNT;
374 }
375