diff options
author | Bad Diode <bd@badd10de.dev> | 2023-04-21 22:47:23 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2023-04-21 22:47:23 +0200 |
commit | 521a0acbb99928c2c67cb1f396968510ec18721c (patch) | |
tree | e1b403bb95564bdde21d84c52bb5c7b1b5a64420 | |
parent | ad741838d5e39d6874a44b1e609c70b486a3ac21 (diff) | |
download | gba-renderers-521a0acbb99928c2c67cb1f396968510ec18721c.tar.gz gba-renderers-521a0acbb99928c2c67cb1f396968510ec18721c.zip |
Add color overwriting/clear for chr sprites
-rw-r--r-- | src/main.c | 34 | ||||
-rw-r--r-- | src/profiling.c | 2 | ||||
-rw-r--r-- | src/renderer.h | 6 | ||||
-rw-r--r-- | src/renderer_m0.c | 21 | ||||
-rw-r--r-- | src/renderer_m4.c | 31 |
5 files changed, 50 insertions, 44 deletions
@@ -50,7 +50,7 @@ test_chr(void) { | |||
50 | 50 | ||
51 | for (size_t y = 10; y < 20; y++) { | 51 | for (size_t y = 10; y < 20; y++) { |
52 | for (size_t x = 20; x < 30; x++) { | 52 | for (size_t x = 20; x < 30; x++) { |
53 | draw_chr(8 + x * 8, 2 + y * 8, tile, 0, 0); | 53 | draw_chr(8 + x * 8, 2 + y * 8, tile, 0, 0, 0); |
54 | } | 54 | } |
55 | } | 55 | } |
56 | } | 56 | } |
@@ -234,14 +234,14 @@ test_sprites_bounce(void) { | |||
234 | int flip_y; | 234 | int flip_y; |
235 | } Sprite; | 235 | } Sprite; |
236 | Sprite sprites[] = { | 236 | Sprite sprites[] = { |
237 | {50, 50, 1, 1, 1, 0, 0}, | 237 | {50 , 50 , 1 , 1 , 0 , 0 , 0}, |
238 | {20, 30, 2, 3, 2, 0, 1}, | 238 | {20 , 30 , 2 , 3 , 1 , 0 , 1}, |
239 | {10, 100, -2, -1, 3, 1, 0}, | 239 | {10 , 100 , -2 , -1 , 2 , 1 , 0}, |
240 | {200, 80, 1, -2, 4, 1, 1}, | 240 | {200 , 75 , 1 , -2 , 3 , 1 , 1}, |
241 | {50, 50, 1, 1, 1, 0, 0}, | 241 | {55 , 45 , -1 , 1 , 4 , 0 , 0}, |
242 | {20, 30, 2, 3, 2, 0, 1}, | 242 | {25 , 35 , 2 , -3 , 5 , 0 , 1}, |
243 | {10, 100, -2, -1, 3, 1, 0}, | 243 | {15 , 95 , -2 , 1 , 6 , 1 , 0}, |
244 | {200, 80, 1, -2, 4, 1, 1}, | 244 | {210 , 75 , 1 , 2 , 15 , 1 , 1}, |
245 | }; | 245 | }; |
246 | int should_move = 1; | 246 | int should_move = 1; |
247 | while (true) { | 247 | while (true) { |
@@ -268,6 +268,7 @@ test_sprites_bounce(void) { | |||
268 | PROF(draw_chr( | 268 | PROF(draw_chr( |
269 | (240 - s->x - 8), (160 - s->y - 8), | 269 | (240 - s->x - 8), (160 - s->y - 8), |
270 | sprite_chr, | 270 | sprite_chr, |
271 | s->clr, | ||
271 | s->flip_x, s->flip_y), chr_cycles); | 272 | s->flip_x, s->flip_y), chr_cycles); |
272 | s->x += s->inc_x * should_move; | 273 | s->x += s->inc_x * should_move; |
273 | s->y += s->inc_y * should_move; | 274 | s->y += s->inc_y * should_move; |
@@ -303,12 +304,12 @@ test_text_rendering(void) { | |||
303 | PROF(flip_buffer(), flip_cycles); | 304 | PROF(flip_buffer(), flip_cycles); |
304 | PROF(screen_fill(0), clear_cycles); | 305 | PROF(screen_fill(0), clear_cycles); |
305 | txt_color(2); | 306 | txt_color(2); |
306 | txt_position(0, 8); | 307 | PROF(txt_drawf("The strongest bulwark of", 4, 8 * 2, 3), txt_drawf_cycles); |
307 | PROF(txt_drawf("The strongest bulwark of", 4, 0, 3), txt_drawf_cycles); | 308 | PROF(txt_drawf("authority is uniformity;", 2, 8 * 3, 3), txt_drawf_cycles); |
308 | PROF(txt_drawf("authority is uniformity;", 2, 8, 3), txt_drawf_cycles); | 309 | PROF(txt_drawf("the least divergence from it", 8, 8 * 4, 3), txt_drawf_cycles); |
309 | PROF(txt_drawf("the least divergence from it", 8, 16, 3), txt_drawf_cycles); | 310 | PROF(txt_drawf("it's the greatest crime", 6, 8 * 5, 3), txt_drawf_cycles); |
310 | PROF(txt_drawf("it's the greatest crime", 6, 24, 3), txt_drawf_cycles); | 311 | PROF(txt_drawf("- Emma Goldman", 100, 8 * 6 + 3, 3), txt_drawf_cycles); |
311 | PROF(txt_drawf("- Emma Goldman", 100, 36, 3), txt_drawf_cycles); | 312 | txt_position(0, 10); |
312 | PROF(txt_printf("The only way to deal with an\n" | 313 | PROF(txt_printf("The only way to deal with an\n" |
313 | "unfree world is to become\n" | 314 | "unfree world is to become\n" |
314 | "so absolutely free,\n" | 315 | "so absolutely free,\n" |
@@ -333,9 +334,6 @@ int main(void) { | |||
333 | irq_init(); | 334 | irq_init(); |
334 | irs_set(IRQ_VBLANK, irs_stub); | 335 | irs_set(IRQ_VBLANK, irs_stub); |
335 | 336 | ||
336 | // TODO: Test for text rendering. | ||
337 | // TODO: Add a clear mode for chr that inverts non zero values to become | ||
338 | // zero, thus clearing the sprite if it was in the same position. | ||
339 | while (true) { | 337 | while (true) { |
340 | test_text_rendering(); | 338 | test_text_rendering(); |
341 | test_growing_rects(); | 339 | test_growing_rects(); |
diff --git a/src/profiling.c b/src/profiling.c index 1686ad9..a464372 100644 --- a/src/profiling.c +++ b/src/profiling.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #define PROF(F,VAR) \ | 18 | #define PROF(F,VAR) \ |
19 | do { \ | 19 | do { \ |
20 | u32 __tmp_prof = profile_measure();\ | 20 | u32 __tmp_prof = profile_measure();\ |
21 | (F);\ | 21 | F;\ |
22 | (VAR) += profile_measure() - __tmp_prof;\ | 22 | (VAR) += profile_measure() - __tmp_prof;\ |
23 | } while (0) | 23 | } while (0) |
24 | 24 | ||
diff --git a/src/renderer.h b/src/renderer.h index cf490d3..e6637ef 100644 --- a/src/renderer.h +++ b/src/renderer.h | |||
@@ -20,8 +20,10 @@ void draw_filled_rect(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr); | |||
20 | void screen_fill(u8 clr); | 20 | void screen_fill(u8 clr); |
21 | 21 | ||
22 | // Draws a chr sprite (16 * u8). The first 8 bytes correspond to ch0 and the | 22 | // Draws a chr sprite (16 * u8). The first 8 bytes correspond to ch0 and the |
23 | // last 8 to ch1. | 23 | // last 8 to ch1. If clr is 0 the regular 4bit color will be used, from clr 1-14 |
24 | void draw_chr(size_t x, size_t y, u8 *sprite, u8 flip_x, u8 flip_y); | 24 | // the given color will overwrite the existing one. Color 15 will "clear" the |
25 | // sprite instead. | ||
26 | void draw_chr(size_t x, size_t y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y); | ||
25 | 27 | ||
26 | // Draws a 1bpp icn sprite in the given color. | 28 | // Draws a 1bpp icn sprite in the given color. |
27 | void draw_icn(size_t x, size_t y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y); | 29 | void draw_icn(size_t x, size_t y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y); |
diff --git a/src/renderer_m0.c b/src/renderer_m0.c index 7e598c3..10bbff5 100644 --- a/src/renderer_m0.c +++ b/src/renderer_m0.c | |||
@@ -460,7 +460,7 @@ decode_1bpp(u8 row, u8 flip_x) { | |||
460 | IWRAM_CODE | 460 | IWRAM_CODE |
461 | static inline | 461 | static inline |
462 | void | 462 | void |
463 | draw_2bpp_row(size_t x, size_t y, u8 a, u8 b, u8 flip_x) { | 463 | draw_2bpp_row(size_t x, size_t y, u8 a, u8 b, u8 clr, u8 flip_x) { |
464 | BOUNDCHECK_SCREEN(x, y); | 464 | BOUNDCHECK_SCREEN(x, y); |
465 | 465 | ||
466 | size_t tile_x = x / 8; | 466 | size_t tile_x = x / 8; |
@@ -482,11 +482,16 @@ draw_2bpp_row(size_t x, size_t y, u8 a, u8 b, u8 flip_x) { | |||
482 | u32 mask_a = (clr_a * 0xF); | 482 | u32 mask_a = (clr_a * 0xF); |
483 | u32 mask_b = (clr_b * 0xF); | 483 | u32 mask_b = (clr_b * 0xF); |
484 | u32 mask = (mask_a | mask_b); | 484 | u32 mask = (mask_a | mask_b); |
485 | u32 color = clr_a + (clr_b << 1); | 485 | u32 color; |
486 | if (clr == 0) { | ||
487 | color = clr_a + (clr_b << 1); | ||
488 | } else if (clr == 15) { | ||
489 | color = 0; | ||
490 | } else { | ||
491 | color = (clr_a | clr_b) * clr; | ||
492 | } | ||
486 | dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left); | 493 | dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left); |
487 | dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right); | 494 | dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right); |
488 | |||
489 | // TODO: different blend modes? | ||
490 | } | 495 | } |
491 | 496 | ||
492 | IWRAM_CODE | 497 | IWRAM_CODE |
@@ -508,27 +513,25 @@ draw_1bpp_row(size_t x, size_t y, u8 a, u8 clr, u8 flip_x) { | |||
508 | color *= clr; | 513 | color *= clr; |
509 | dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left); | 514 | dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left); |
510 | dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right); | 515 | dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right); |
511 | |||
512 | // TODO: different blend modes? | ||
513 | } | 516 | } |
514 | 517 | ||
515 | IWRAM_CODE | 518 | IWRAM_CODE |
516 | void | 519 | void |
517 | draw_chr(size_t x, size_t y, u8 *sprite, u8 flip_x, u8 flip_y) { | 520 | draw_chr(size_t x, size_t y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) { |
518 | BOUNDCHECK_SCREEN(x, y); | 521 | BOUNDCHECK_SCREEN(x, y); |
519 | if (!flip_y) { | 522 | if (!flip_y) { |
520 | for(size_t v = 0; v < 8; v++) { | 523 | for(size_t v = 0; v < 8; v++) { |
521 | if ((y + v) >= SCREEN_HEIGHT) break; | 524 | if ((y + v) >= SCREEN_HEIGHT) break; |
522 | u8 ch1 = sprite[v + 0]; | 525 | u8 ch1 = sprite[v + 0]; |
523 | u8 ch2 = sprite[v + 8]; | 526 | u8 ch2 = sprite[v + 8]; |
524 | draw_2bpp_row(x, y + v, ch1, ch2, flip_x); | 527 | draw_2bpp_row(x, y + v, ch1, ch2, clr, flip_x); |
525 | } | 528 | } |
526 | } else { | 529 | } else { |
527 | for(size_t v = 0; v < 8; v++) { | 530 | for(size_t v = 0; v < 8; v++) { |
528 | if ((y + v) >= SCREEN_HEIGHT) break; | 531 | if ((y + v) >= SCREEN_HEIGHT) break; |
529 | u8 ch1 = sprite[(7 - v) + 0]; | 532 | u8 ch1 = sprite[(7 - v) + 0]; |
530 | u8 ch2 = sprite[(7 - v) + 8]; | 533 | u8 ch2 = sprite[(7 - v) + 8]; |
531 | draw_2bpp_row(x, y + v, ch1, ch2, flip_x); | 534 | draw_2bpp_row(x, y + v, ch1, ch2, clr, flip_x); |
532 | } | 535 | } |
533 | } | 536 | } |
534 | } | 537 | } |
diff --git a/src/renderer_m4.c b/src/renderer_m4.c index 73b51d5..657bb73 100644 --- a/src/renderer_m4.c +++ b/src/renderer_m4.c | |||
@@ -45,9 +45,9 @@ draw_pixel(size_t x, size_t y, u8 clr) { | |||
45 | BOUNDCHECK_SCREEN(x, y); | 45 | BOUNDCHECK_SCREEN(x, y); |
46 | u16 *dst = &backbuf[(x + y * SCREEN_WIDTH) / 2]; | 46 | u16 *dst = &backbuf[(x + y * SCREEN_WIDTH) / 2]; |
47 | if(x & 1) { | 47 | if(x & 1) { |
48 | *dst = (*dst & 0xFF) | (clr << 8); | 48 | *dst = (*dst & 0xF) | (clr << 8); |
49 | } else { | 49 | } else { |
50 | *dst = (*dst & ~0xFF) | clr; | 50 | *dst = (*dst & ~0xF) | clr; |
51 | } | 51 | } |
52 | } | 52 | } |
53 | 53 | ||
@@ -100,13 +100,13 @@ draw_vline(size_t x0, size_t y0, size_t y1, u8 clr) { | |||
100 | size_t tile_x0 = x0 / 8; | 100 | size_t tile_x0 = x0 / 8; |
101 | size_t start_col = x0 % 8; | 101 | size_t start_col = x0 % 8; |
102 | u16 *dst = &backbuf[(start_col + tile_x0 * 8 + y0 * SCREEN_WIDTH) / 2]; | 102 | u16 *dst = &backbuf[(start_col + tile_x0 * 8 + y0 * SCREEN_WIDTH) / 2]; |
103 | if(start_col & 1) { | 103 | if(x0 & 1) { |
104 | for (size_t i = 0; i <= y1 - y0; i++, dst += SCREEN_WIDTH / 2) { | 104 | for (size_t i = 0; i <= y1 - y0; i++, dst += SCREEN_WIDTH / 2) { |
105 | *dst = (*dst & 0xFF) | (clr << 8); | 105 | *dst = (*dst & 0xF) | (clr << 8); |
106 | } | 106 | } |
107 | } else { | 107 | } else { |
108 | for (size_t i = 0; i <= y1 - y0; i++, dst += SCREEN_WIDTH / 2) { | 108 | for (size_t i = 0; i <= y1 - y0; i++, dst += SCREEN_WIDTH / 2) { |
109 | *dst = (*dst & ~0xFF) | clr; | 109 | *dst = (*dst & ~0xF) | clr; |
110 | } | 110 | } |
111 | } | 111 | } |
112 | } | 112 | } |
@@ -439,7 +439,7 @@ decode_1bpp(u8 row, u8 flip_x) { | |||
439 | IWRAM_CODE | 439 | IWRAM_CODE |
440 | static inline | 440 | static inline |
441 | void | 441 | void |
442 | draw_2bpp_row(size_t x, size_t y, u8 a, u8 b, u8 flip_x) { | 442 | draw_2bpp_row(size_t x, size_t y, u8 a, u8 b, u8 clr, u8 flip_x) { |
443 | BOUNDCHECK_SCREEN(x, y); | 443 | BOUNDCHECK_SCREEN(x, y); |
444 | 444 | ||
445 | size_t tile_x = x / 8; | 445 | size_t tile_x = x / 8; |
@@ -459,11 +459,16 @@ draw_2bpp_row(size_t x, size_t y, u8 a, u8 b, u8 flip_x) { | |||
459 | u64 mask_a = (clr_a * 0xF); | 459 | u64 mask_a = (clr_a * 0xF); |
460 | u64 mask_b = (clr_b * 0xF); | 460 | u64 mask_b = (clr_b * 0xF); |
461 | u64 mask = (mask_a | mask_b); | 461 | u64 mask = (mask_a | mask_b); |
462 | u64 color = clr_a + (clr_b << 1); | 462 | u64 color; |
463 | if (clr == 0) { | ||
464 | color = clr_a + (clr_b << 1); | ||
465 | } else if (clr == 15) { | ||
466 | color = 0; | ||
467 | } else { | ||
468 | color = (clr_a | clr_b) * clr; | ||
469 | } | ||
463 | dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left); | 470 | dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left); |
464 | dst[1] = (dst[1] & ~(mask >> shift_right)) | (color >> shift_right); | 471 | dst[1] = (dst[1] & ~(mask >> shift_right)) | (color >> shift_right); |
465 | |||
466 | // TODO: different blend modes? | ||
467 | } | 472 | } |
468 | 473 | ||
469 | IWRAM_CODE | 474 | IWRAM_CODE |
@@ -483,27 +488,25 @@ draw_1bpp_row(size_t x, size_t y, u8 a, u8 clr, u8 flip_x) { | |||
483 | color *= clr; | 488 | color *= clr; |
484 | dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left); | 489 | dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left); |
485 | dst[1] = (dst[1] & ~(mask >> shift_right)) | (color >> shift_right); | 490 | dst[1] = (dst[1] & ~(mask >> shift_right)) | (color >> shift_right); |
486 | |||
487 | // TODO: different blend modes? | ||
488 | } | 491 | } |
489 | 492 | ||
490 | IWRAM_CODE | 493 | IWRAM_CODE |
491 | void | 494 | void |
492 | draw_chr(size_t x, size_t y, u8 *sprite, u8 flip_x, u8 flip_y) { | 495 | draw_chr(size_t x, size_t y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) { |
493 | BOUNDCHECK_SCREEN(x, y); | 496 | BOUNDCHECK_SCREEN(x, y); |
494 | if (!flip_y) { | 497 | if (!flip_y) { |
495 | for(size_t v = 0; v < 8; v++) { | 498 | for(size_t v = 0; v < 8; v++) { |
496 | if ((y + v) >= SCREEN_HEIGHT) break; | 499 | if ((y + v) >= SCREEN_HEIGHT) break; |
497 | u8 ch1 = sprite[v + 0]; | 500 | u8 ch1 = sprite[v + 0]; |
498 | u8 ch2 = sprite[v + 8]; | 501 | u8 ch2 = sprite[v + 8]; |
499 | draw_2bpp_row(x, y + v, ch1, ch2, flip_x); | 502 | draw_2bpp_row(x, y + v, ch1, ch2, clr, flip_x); |
500 | } | 503 | } |
501 | } else { | 504 | } else { |
502 | for(size_t v = 0; v < 8; v++) { | 505 | for(size_t v = 0; v < 8; v++) { |
503 | if ((y + v) >= SCREEN_HEIGHT) break; | 506 | if ((y + v) >= SCREEN_HEIGHT) break; |
504 | u8 ch1 = sprite[(7 - v) + 0]; | 507 | u8 ch1 = sprite[(7 - v) + 0]; |
505 | u8 ch2 = sprite[(7 - v) + 8]; | 508 | u8 ch2 = sprite[(7 - v) + 8]; |
506 | draw_2bpp_row(x, y + v, ch1, ch2, flip_x); | 509 | draw_2bpp_row(x, y + v, ch1, ch2, clr, flip_x); |
507 | } | 510 | } |
508 | } | 511 | } |
509 | } | 512 | } |