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