Mercurial > vba-linux
comparison src/gb/gbGfx.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 #include <cstring> | |
2 | |
3 #include "gbGlobals.h" | |
4 #include "gbSGB.h" | |
5 | |
6 extern int32 layerSettings; | |
7 | |
8 u8 gbInvertTab[256] = { | |
9 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, | |
10 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, | |
11 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, | |
12 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, | |
13 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, | |
14 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, | |
15 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, | |
16 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, | |
17 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, | |
18 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, | |
19 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, | |
20 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, | |
21 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, | |
22 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, | |
23 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, | |
24 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, | |
25 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, | |
26 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, | |
27 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, | |
28 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, | |
29 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, | |
30 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, | |
31 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, | |
32 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, | |
33 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, | |
34 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, | |
35 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, | |
36 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, | |
37 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, | |
38 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, | |
39 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, | |
40 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff | |
41 }; | |
42 | |
43 u16 gbLineMix[160]; | |
44 | |
45 void gbRenderLine() | |
46 { | |
47 u8 *bank0; | |
48 u8 *bank1; | |
49 if (gbCgbMode) | |
50 { | |
51 bank0 = &gbVram[0x0000]; | |
52 bank1 = &gbVram[0x2000]; | |
53 } | |
54 else | |
55 { | |
56 bank0 = &gbMemory[0x8000]; | |
57 bank1 = NULL; | |
58 } | |
59 | |
60 int tile_map = 0x1800; | |
61 if ((register_LCDC & 8) != 0) | |
62 tile_map = 0x1c00; | |
63 | |
64 int tile_pattern = 0x0800; | |
65 | |
66 if ((register_LCDC & 16) != 0) | |
67 tile_pattern = 0x0000; | |
68 | |
69 int x = 0; | |
70 int y = register_LY; | |
71 | |
72 if (y >= 144) | |
73 return; | |
74 | |
75 // int yLine = (y + gbBorderRowSkip) * gbBorderLineSkip; | |
76 | |
77 int sx = register_SCX; | |
78 int sy = register_SCY; | |
79 | |
80 sy += y; | |
81 | |
82 sy &= 255; | |
83 | |
84 int tx = sx >> 3; | |
85 int ty = sy >> 3; | |
86 | |
87 int bx = 1 << (7 - (sx & 7)); | |
88 int by = sy & 7; | |
89 | |
90 int tile_map_line_y = tile_map + ty * 32; | |
91 | |
92 int tile_map_address = tile_map_line_y + tx; | |
93 | |
94 u8 attrs = 0; | |
95 if (bank1 != NULL) | |
96 attrs = bank1[tile_map_address]; | |
97 | |
98 u8 tile = bank0[tile_map_address]; | |
99 | |
100 tile_map_address++; | |
101 | |
102 if ((register_LCDC & 16) == 0) | |
103 { | |
104 if (tile < 128) | |
105 tile += 128; | |
106 else | |
107 tile -= 128; | |
108 } | |
109 | |
110 int tile_pattern_address = tile_pattern + tile * 16 + by*2; | |
111 | |
112 if (register_LCDC & 0x80) | |
113 { | |
114 if ((register_LCDC & 0x01 || gbCgbMode) && (layerSettings & 0x0100)) | |
115 { | |
116 while (x < 160) | |
117 { | |
118 u8 tile_a = 0; | |
119 u8 tile_b = 0; | |
120 | |
121 if (attrs & 0x40) | |
122 { | |
123 tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2; | |
124 } | |
125 | |
126 if (attrs & 0x08) | |
127 { | |
128 tile_a = bank1[tile_pattern_address++]; | |
129 tile_b = bank1[tile_pattern_address]; | |
130 } | |
131 else | |
132 { | |
133 tile_a = bank0[tile_pattern_address++]; | |
134 tile_b = bank0[tile_pattern_address]; | |
135 } | |
136 | |
137 if (attrs & 0x20) | |
138 { | |
139 tile_a = gbInvertTab[tile_a]; | |
140 tile_b = gbInvertTab[tile_b]; | |
141 } | |
142 | |
143 while (bx > 0) | |
144 { | |
145 u8 c = (tile_a & bx) ? 1 : 0; | |
146 c += ((tile_b & bx) ? 2 : 0); | |
147 | |
148 gbLineBuffer[x] = c; // mark the gbLineBuffer color | |
149 | |
150 if (attrs & 0x80) | |
151 gbLineBuffer[x] |= 0x300; | |
152 | |
153 if (gbCgbMode) | |
154 { | |
155 c = c + (attrs & 7)*4; | |
156 } | |
157 else | |
158 { | |
159 c = gbBgp[c]; | |
160 if (gbSgbMode && !gbCgbMode) | |
161 { | |
162 int dx = x >> 3; | |
163 int dy = y >> 3; | |
164 | |
165 int palette = gbSgbATF[dy * 20 + dx]; | |
166 | |
167 if (c == 0) | |
168 palette = 0; | |
169 | |
170 c = c + 4*palette; | |
171 } | |
172 } | |
173 gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] : | |
174 gbPalette[c]; | |
175 x++; | |
176 if (x >= 160) | |
177 break; | |
178 bx >>= 1; | |
179 } | |
180 tx++; | |
181 if (tx == 32) | |
182 tx = 0; | |
183 bx = 128; | |
184 | |
185 if (bank1) | |
186 attrs = bank1[tile_map_line_y + tx]; | |
187 | |
188 tile = bank0[tile_map_line_y + tx]; | |
189 | |
190 if ((register_LCDC & 16) == 0) | |
191 { | |
192 if (tile < 128) | |
193 tile += 128; | |
194 else | |
195 tile -= 128; | |
196 } | |
197 tile_pattern_address = tile_pattern + tile * 16 + by * 2; | |
198 } | |
199 } | |
200 else | |
201 { | |
202 for (int i = 0; i < 160; i++) | |
203 { | |
204 gbLineMix[i] = gbPalette[0]; | |
205 gbLineBuffer[i] = 0; | |
206 } | |
207 } | |
208 | |
209 // do the window display | |
210 if ((register_LCDC & 0x20) && (layerSettings & 0x2000)) | |
211 { | |
212 int wy = register_WY; | |
213 | |
214 if (y >= wy) | |
215 { | |
216 int wx = register_WX; | |
217 wx -= 7; | |
218 | |
219 if (wx <= 159 && gbWindowLine <= 143) | |
220 { | |
221 tile_map = 0x1800; | |
222 | |
223 if ((register_LCDC & 0x40) != 0) | |
224 tile_map = 0x1c00; | |
225 | |
226 if (gbWindowLine == -1) | |
227 { | |
228 gbWindowLine = 0; | |
229 } | |
230 | |
231 tx = 0; | |
232 ty = gbWindowLine >> 3; | |
233 | |
234 bx = 128; | |
235 by = gbWindowLine & 7; | |
236 | |
237 if (wx < 0) | |
238 { | |
239 bx >>= (-wx); | |
240 wx = 0; | |
241 } | |
242 | |
243 tile_map_line_y = tile_map + ty * 32; | |
244 | |
245 tile_map_address = tile_map_line_y + tx; | |
246 | |
247 x = wx; | |
248 | |
249 tile = bank0[tile_map_address]; | |
250 u8 attrs = 0; | |
251 if (bank1) | |
252 attrs = bank1[tile_map_address]; | |
253 tile_map_address++; | |
254 | |
255 if ((register_LCDC & 16) == 0) | |
256 { | |
257 if (tile < 128) | |
258 tile += 128; | |
259 else | |
260 tile -= 128; | |
261 } | |
262 | |
263 tile_pattern_address = tile_pattern + tile * 16 + by*2; | |
264 | |
265 while (x < 160) | |
266 { | |
267 u8 tile_a = 0; | |
268 u8 tile_b = 0; | |
269 | |
270 if (attrs & 0x40) | |
271 { | |
272 tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2; | |
273 } | |
274 | |
275 if (attrs & 0x08) | |
276 { | |
277 tile_a = bank1[tile_pattern_address++]; | |
278 tile_b = bank1[tile_pattern_address]; | |
279 } | |
280 else | |
281 { | |
282 tile_a = bank0[tile_pattern_address++]; | |
283 tile_b = bank0[tile_pattern_address]; | |
284 } | |
285 | |
286 if (attrs & 0x20) | |
287 { | |
288 tile_a = gbInvertTab[tile_a]; | |
289 tile_b = gbInvertTab[tile_b]; | |
290 } | |
291 | |
292 while (bx > 0) | |
293 { | |
294 u8 c = (tile_a & bx) != 0 ? 1 : 0; | |
295 c += ((tile_b & bx) != 0 ? 2 : 0); | |
296 | |
297 if (attrs & 0x80) | |
298 gbLineBuffer[x] = 0x300 + c; | |
299 else | |
300 gbLineBuffer[x] = 0x100 + c; | |
301 | |
302 if (gbCgbMode) | |
303 { | |
304 c = c + (attrs & 7) * 4; | |
305 } | |
306 else | |
307 { | |
308 c = gbBgp[c]; | |
309 if (gbSgbMode && !gbCgbMode) | |
310 { | |
311 int dx = x >> 3; | |
312 int dy = y >> 3; | |
313 | |
314 int palette = gbSgbATF[dy * 20 + dx]; | |
315 | |
316 if (c == 0) | |
317 palette = 0; | |
318 | |
319 c = c + 4*palette; | |
320 } | |
321 } | |
322 gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] : | |
323 gbPalette[c]; | |
324 x++; | |
325 if (x >= 160) | |
326 break; | |
327 bx >>= 1; | |
328 } | |
329 tx++; | |
330 if (tx == 32) | |
331 tx = 0; | |
332 bx = 128; | |
333 tile = bank0[tile_map_line_y + tx]; | |
334 if (bank1) | |
335 attrs = bank1[tile_map_line_y + tx]; | |
336 | |
337 if ((register_LCDC & 16) == 0) | |
338 { | |
339 if (tile < 128) | |
340 tile += 128; | |
341 else | |
342 tile -= 128; | |
343 } | |
344 tile_pattern_address = tile_pattern + tile * 16 + by * 2; | |
345 } | |
346 gbWindowLine++; | |
347 } | |
348 } | |
349 } | |
350 } | |
351 else | |
352 { | |
353 for (int i = 0; i < 160; i++) | |
354 { | |
355 gbLineMix[i] = gbPalette[0]; | |
356 gbLineBuffer[i] = 0; | |
357 } | |
358 } | |
359 } | |
360 | |
361 void gbDrawSpriteTile(int tile, int x, int y, int t, int flags, | |
362 int size, int spriteNumber) | |
363 { | |
364 u8 *bank0; | |
365 u8 *bank1; | |
366 if (gbCgbMode) | |
367 { | |
368 if (register_VBK & 1) | |
369 { | |
370 bank0 = &gbVram[0x0000]; | |
371 bank1 = &gbVram[0x2000]; | |
372 } | |
373 else | |
374 { | |
375 bank0 = &gbVram[0x0000]; | |
376 bank1 = &gbVram[0x2000]; | |
377 } | |
378 } | |
379 else | |
380 { | |
381 bank0 = &gbMemory[0x8000]; | |
382 bank1 = NULL; | |
383 } | |
384 | |
385 int init = 0x0000; | |
386 | |
387 // int yLine = (y+gbBorderRowSkip) * gbBorderLineSkip; | |
388 | |
389 u8 *pal = gbObp0; | |
390 | |
391 int flipx = (flags & 0x20); | |
392 int flipy = (flags & 0x40); | |
393 | |
394 if ((flags & 0x10)) | |
395 pal = gbObp1; | |
396 | |
397 if (flipy) | |
398 { | |
399 t = (size ? 15 : 7) - t; | |
400 } | |
401 | |
402 int prio = flags & 0x80; | |
403 | |
404 int address = init + tile * 16 + 2*t; | |
405 int a = 0; | |
406 int b = 0; | |
407 | |
408 if (gbCgbMode && flags & 0x08) | |
409 { | |
410 a = bank1[address++]; | |
411 b = bank1[address++]; | |
412 } | |
413 else | |
414 { | |
415 a = bank0[address++]; | |
416 b = bank0[address++]; | |
417 } | |
418 | |
419 for (int xx = 0; xx < 8; xx++) | |
420 { | |
421 u8 mask = 1 << (7-xx); | |
422 u8 c = 0; | |
423 if ((a & mask)) | |
424 c++; | |
425 if ((b & mask)) | |
426 c += 2; | |
427 | |
428 if (c == 0) | |
429 continue; | |
430 | |
431 int xxx = xx+x; | |
432 if (flipx) | |
433 xxx = (7-xx+x); | |
434 | |
435 if (xxx < 0 || xxx > 159) | |
436 continue; | |
437 | |
438 u16 color = gbLineBuffer[xxx]; | |
439 | |
440 if (prio) | |
441 { | |
442 if (color < 0x200 && ((color & 0xFF) != 0)) | |
443 continue; | |
444 } | |
445 if (color >= 0x300 && color != 0x300) | |
446 continue; | |
447 else if (color >= 0x200 && color < 0x300) | |
448 { | |
449 int sprite = color & 0xff; | |
450 | |
451 int spriteX = gbMemory[0xfe00 + 4 * sprite + 1] - 8; | |
452 | |
453 if (spriteX == x) | |
454 { | |
455 if (sprite < spriteNumber) | |
456 continue; | |
457 } | |
458 else | |
459 { | |
460 if (gbCgbMode) | |
461 { | |
462 if (sprite < spriteNumber) | |
463 continue; | |
464 } | |
465 else | |
466 { | |
467 if (spriteX < x+8) | |
468 continue; | |
469 } | |
470 } | |
471 } | |
472 | |
473 gbLineBuffer[xxx] = 0x200 + spriteNumber; | |
474 | |
475 // make sure that sprites will work even in CGB mode | |
476 if (gbCgbMode) | |
477 { | |
478 c = c + (flags & 0x07)*4 + 32; | |
479 } | |
480 else | |
481 { | |
482 c = pal[c]; | |
483 | |
484 if (gbSgbMode && !gbCgbMode) | |
485 { | |
486 int dx = xxx >> 3; | |
487 int dy = y >> 3; | |
488 | |
489 int palette = gbSgbATF[dy * 20 + dx]; | |
490 | |
491 if (c == 0) | |
492 palette = 0; | |
493 | |
494 c = c + 4*palette; | |
495 } | |
496 else | |
497 { | |
498 c += 4; | |
499 } | |
500 } | |
501 | |
502 gbLineMix[xxx] = gbColorOption ? gbColorFilter[gbPalette[c]] : | |
503 gbPalette[c]; | |
504 } | |
505 } | |
506 | |
507 void gbDrawSprites() | |
508 { | |
509 int x = 0; | |
510 int y = 0; | |
511 int count = 0; | |
512 | |
513 int size = (register_LCDC & 4); | |
514 | |
515 if (!(register_LCDC & 0x80)) | |
516 return; | |
517 | |
518 if ((register_LCDC & 2) && (layerSettings & 0x1000)) | |
519 { | |
520 int yc = register_LY; | |
521 | |
522 int address = 0xfe00; | |
523 for (int i = 0; i < 40; i++) | |
524 { | |
525 y = gbMemory[address++]; | |
526 x = gbMemory[address++]; | |
527 int tile = gbMemory[address++]; | |
528 if (size) | |
529 tile &= 254; | |
530 int flags = gbMemory[address++]; | |
531 | |
532 if (x > 0 && y > 0 && x < 168 && y < 160) | |
533 { | |
534 // check if sprite intersects current line | |
535 int t = yc -y + 16; | |
536 if (size && t >= 0 && t < 16) | |
537 { | |
538 gbDrawSpriteTile(tile, x-8, yc, t, flags, size, i); | |
539 count++; | |
540 } | |
541 else if (!size && t >= 0 && t < 8) | |
542 { | |
543 gbDrawSpriteTile(tile, x-8, yc, t, flags, size, i); | |
544 count++; | |
545 } | |
546 } | |
547 // sprite limit reached! | |
548 if (count >= 10) | |
549 break; | |
550 } | |
551 } | |
552 } |