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