summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-04-22 10:30:18 +0200
committerBad Diode <bd@badd10de.dev>2023-04-22 10:30:18 +0200
commit60c54f82fba2114ae1bceb81c4cd99d164f1f9f3 (patch)
tree63ca191145eac03200367a60a152d9351e240fbc
parente17dbbd6b6f6314d84e719fd7ef7653f76fa388f (diff)
downloadgba-link-cable-tester-60c54f82fba2114ae1bceb81c4cd99d164f1f9f3.tar.gz
gba-link-cable-tester-60c54f82fba2114ae1bceb81c4cd99d164f1f9f3.zip
Add dirty tiles and dirty lines method for buffer flipping
-rw-r--r--src/main.c24
-rw-r--r--src/profiling.c2
-rw-r--r--src/renderer_m0.c70
3 files changed, 70 insertions, 26 deletions
diff --git a/src/main.c b/src/main.c
index d97a110..55edea1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -244,6 +244,8 @@ test_sprites_bounce(void) {
244 {210 , 75 , 1 , 2 , 15 , 1 , 1}, 244 {210 , 75 , 1 , 2 , 15 , 1 , 1},
245 }; 245 };
246 int should_move = 1; 246 int should_move = 1;
247 screen_fill(8);
248 flip_buffer();
247 while (true) { 249 while (true) {
248 poll_keys(); 250 poll_keys();
249 if (key_tap(KEY_A)) { 251 if (key_tap(KEY_A)) {
@@ -257,12 +259,26 @@ test_sprites_bounce(void) {
257 bios_vblank_wait(); 259 bios_vblank_wait();
258 FRAME_START(); 260 FRAME_START();
259 PROF(flip_buffer(), flip_cycles); 261 PROF(flip_buffer(), flip_cycles);
262#if FLIP_TYPE == 0
260 PROF(screen_fill(8), clear_cycles); 263 PROF(screen_fill(8), clear_cycles);
261 for (size_t i = 0; i < LEN(sprites); i++) { 264#endif
265 for (size_t i = 0; i < LEN(sprites) * should_move; i++) {
262 Sprite *s = &sprites[i]; 266 Sprite *s = &sprites[i];
263 PROF(draw_icn( 267 PROF(draw_icn(
264 s->x, s->y, 268 s->x, s->y,
265 sprite_icn, 269 sprite_icn,
270 8,
271 s->flip_x, s->flip_y), icn_cycles);
272 PROF(draw_chr(
273 (240 - s->x - 8), (160 - s->y - 8),
274 sprite_chr,
275 8,
276 s->flip_x, s->flip_y), chr_cycles);
277 s->x += s->inc_x;
278 s->y += s->inc_y;
279 PROF(draw_icn(
280 s->x, s->y,
281 sprite_icn,
266 s->clr, 282 s->clr,
267 s->flip_x, s->flip_y), icn_cycles); 283 s->flip_x, s->flip_y), icn_cycles);
268 PROF(draw_chr( 284 PROF(draw_chr(
@@ -270,20 +286,14 @@ test_sprites_bounce(void) {
270 sprite_chr, 286 sprite_chr,
271 s->clr, 287 s->clr,
272 s->flip_x, s->flip_y), chr_cycles); 288 s->flip_x, s->flip_y), chr_cycles);
273 s->x += s->inc_x * should_move;
274 s->y += s->inc_y * should_move;
275 if (s->x > (240 - 8) && s->inc_x > 0) { 289 if (s->x > (240 - 8) && s->inc_x > 0) {
276 s->x = (240 - 8);
277 s->inc_x *= -1; 290 s->inc_x *= -1;
278 } else if (s->x <= 0 && s->inc_x < 0){ 291 } else if (s->x <= 0 && s->inc_x < 0){
279 s->x = 0;
280 s->inc_x *= -1; 292 s->inc_x *= -1;
281 } 293 }
282 if (s->y > (160 - 8) && s->inc_y > 0) { 294 if (s->y > (160 - 8) && s->inc_y > 0) {
283 s->y = 160 - 8;
284 s->inc_y *= -1; 295 s->inc_y *= -1;
285 } else if (s->y <= 0 && s->inc_y < 0){ 296 } else if (s->y <= 0 && s->inc_y < 0){
286 s->y = 0;
287 s->inc_y *= -1; 297 s->inc_y *= -1;
288 } 298 }
289 } 299 }
diff --git a/src/profiling.c b/src/profiling.c
index 4475aa8..a464372 100644
--- a/src/profiling.c
+++ b/src/profiling.c
@@ -41,7 +41,7 @@
41#endif 41#endif
42 42
43static bool profile_show = true; 43static bool profile_show = true;
44static bool profile_bg_show = false; 44static bool profile_bg_show = true;
45 45
46#define PROF_SHOW() \ 46#define PROF_SHOW() \
47 do { \ 47 do { \
diff --git a/src/renderer_m0.c b/src/renderer_m0.c
index ecb0402..e4d2dfc 100644
--- a/src/renderer_m0.c
+++ b/src/renderer_m0.c
@@ -14,6 +14,7 @@
14 14
15#define SUBPIXEL_LINES 1 15#define SUBPIXEL_LINES 1
16#define DEC_BIG_LUT 1 16#define DEC_BIG_LUT 1
17#define FLIP_TYPE 2
17 18
18// Front/back buffers for double buffering. 19// Front/back buffers for double buffering.
19#define BUF_0 ((u32*)(MEM_VRAM)) 20#define BUF_0 ((u32*)(MEM_VRAM))
@@ -53,11 +54,20 @@ static u32 dirty_tiles[21] = {0};
53// Basic primitives. 54// Basic primitives.
54// 55//
55 56
57static inline
58void
59redraw(void) {
60 for (size_t i = 0; i < 21; i++) {
61 dirty_tiles[i] = 0xFFFFFFFF;
62 }
63}
64
56IWRAM_CODE 65IWRAM_CODE
57void screen_fill(u8 clr) { 66void screen_fill(u8 clr) {
58 // We have to make sure we leave the last tile blank to use as alpha channel 67 // We have to make sure we leave the last tile blank to use as alpha channel
59 // when moving the BG during double buffering. 68 // when moving the BG during double buffering.
60 dma_fill(backbuf, 0x11111111 * clr, KB(20) - 32, 3); 69 dma_fill(backbuf, 0x11111111 * clr, KB(20) - 32, 3);
70 redraw();
61} 71}
62 72
63IWRAM_CODE 73IWRAM_CODE
@@ -613,8 +623,8 @@ draw_icn(size_t x, size_t y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) {
613IWRAM_CODE 623IWRAM_CODE
614void 624void
615flip_buffer(void) { 625flip_buffer(void) {
616 // NOTE: can this be branchless? Either way is probably unnecessary other 626// Mode 0: double buffering without dirty tiles.
617 // than code clarity maybe?. 627#if FLIP_TYPE == 0
618 if (backbuf == BUF_0) { 628 if (backbuf == BUF_0) {
619 backbuf = BUF_1; 629 backbuf = BUF_1;
620 BG_H_SCROLL_0 = 0; 630 BG_H_SCROLL_0 = 0;
@@ -624,22 +634,46 @@ flip_buffer(void) {
624 BG_H_SCROLL_0 = -240; 634 BG_H_SCROLL_0 = -240;
625 BG_H_SCROLL_1 = 0; 635 BG_H_SCROLL_1 = 0;
626 } 636 }
627 // TODO: Copying all tiles for now. Study if it's better to use dirty_tiles 637
628 // or dirty_lines. 638// Mode 1: single buffer, copy the dirty lines from backbuffer (BUF_1) to
629 // Copy dirty tiles from the backbuffer to the frontbuffer. 639// frontbuffer (BUF_0) using the DMA.
630 // Tile *dst = FRONTBUF; 640#elif FLIP_TYPE == 1
631 // Tile *src = backbuf; 641 u32 *front = BUF_0;
632 // for (size_t j = 0; j < 20; ++j) { 642 u32 *back = BUF_1;
633 // // if (dirty_tiles[j] == 0) { 643 BG_H_SCROLL_0 = 0;
634 // // continue; 644 BG_H_SCROLL_1 = -240;
635 // // } 645 for (size_t j = 0; j < 20; ++j) {
636 // for (size_t i = 0, k = 1; i < 30; ++i, k <<= 1) { 646 if (dirty_tiles[j] == 0) {
637 // // if (dirty_tiles[j] & k) { 647 continue;
638 // dst[i + j * 32] = src[i + j * 32]; 648 }
639 // // } 649 u32 offset = j * 32 * 8;
640 // } 650 dma_copy(front + offset, back + offset, (30 * 8 * 4), 3);
641 // // dirty_tiles[j] = 0; 651 dirty_tiles[j] = 0;
642 // } 652 }
653
654// Mode 2: single buffer, copy the dirty tiles from backbuffer (BUF_1) to
655// frontbuffer (BUF_0).
656#elif FLIP_TYPE == 2
657 u32 *front = BUF_0;
658 u32 *back = BUF_1;
659 BG_H_SCROLL_0 = 0;
660 BG_H_SCROLL_1 = -240;
661 for (size_t j = 0; j < 20; ++j) {
662 if (dirty_tiles[j] == 0) {
663 continue;
664 }
665 u32 offset = j * 32 * 8;
666 size_t k = 1;
667 for (size_t i = 0; i < 30; ++i, k <<= 1) {
668 if (dirty_tiles[j] & k) {
669 Tile *mem_front = front;
670 Tile *mem_back = back;
671 mem_front[i + j * 32] = mem_back[i + j * 32];
672 }
673 }
674 dirty_tiles[j] = 0;
675 }
676#endif
643} 677}
644 678
645// 679//