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