summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-04-21 22:47:23 +0200
committerBad Diode <bd@badd10de.dev>2023-04-21 22:47:23 +0200
commit521a0acbb99928c2c67cb1f396968510ec18721c (patch)
treee1b403bb95564bdde21d84c52bb5c7b1b5a64420
parentad741838d5e39d6874a44b1e609c70b486a3ac21 (diff)
downloadgba-link-cable-tester-521a0acbb99928c2c67cb1f396968510ec18721c.tar.gz
gba-link-cable-tester-521a0acbb99928c2c67cb1f396968510ec18721c.zip
Add color overwriting/clear for chr sprites
-rw-r--r--src/main.c34
-rw-r--r--src/profiling.c2
-rw-r--r--src/renderer.h6
-rw-r--r--src/renderer_m0.c21
-rw-r--r--src/renderer_m4.c31
5 files changed, 50 insertions, 44 deletions
diff --git a/src/main.c b/src/main.c
index f531481..fa2384f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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);
20void screen_fill(u8 clr); 20void 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
24void 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.
26void 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.
27void draw_icn(size_t x, size_t y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y); 29void 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) {
460IWRAM_CODE 460IWRAM_CODE
461static inline 461static inline
462void 462void
463draw_2bpp_row(size_t x, size_t y, u8 a, u8 b, u8 flip_x) { 463draw_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
492IWRAM_CODE 497IWRAM_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
515IWRAM_CODE 518IWRAM_CODE
516void 519void
517draw_chr(size_t x, size_t y, u8 *sprite, u8 flip_x, u8 flip_y) { 520draw_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) {
439IWRAM_CODE 439IWRAM_CODE
440static inline 440static inline
441void 441void
442draw_2bpp_row(size_t x, size_t y, u8 a, u8 b, u8 flip_x) { 442draw_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
469IWRAM_CODE 474IWRAM_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
490IWRAM_CODE 493IWRAM_CODE
491void 494void
492draw_chr(size_t x, size_t y, u8 *sprite, u8 flip_x, u8 flip_y) { 495draw_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}