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