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