diff options
author | Bad Diode <bd@badd10de.dev> | 2023-04-22 10:30:18 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2023-04-22 10:30:18 +0200 |
commit | 60c54f82fba2114ae1bceb81c4cd99d164f1f9f3 (patch) | |
tree | 63ca191145eac03200367a60a152d9351e240fbc | |
parent | e17dbbd6b6f6314d84e719fd7ef7653f76fa388f (diff) | |
download | gba-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.c | 24 | ||||
-rw-r--r-- | src/profiling.c | 2 | ||||
-rw-r--r-- | src/renderer_m0.c | 70 |
3 files changed, 70 insertions, 26 deletions
@@ -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 | ||
43 | static bool profile_show = true; | 43 | static bool profile_show = true; |
44 | static bool profile_bg_show = false; | 44 | static 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 | ||
57 | static inline | ||
58 | void | ||
59 | redraw(void) { | ||
60 | for (size_t i = 0; i < 21; i++) { | ||
61 | dirty_tiles[i] = 0xFFFFFFFF; | ||
62 | } | ||
63 | } | ||
64 | |||
56 | IWRAM_CODE | 65 | IWRAM_CODE |
57 | void screen_fill(u8 clr) { | 66 | void 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 | ||
63 | IWRAM_CODE | 73 | IWRAM_CODE |
@@ -613,8 +623,8 @@ draw_icn(size_t x, size_t y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) { | |||
613 | IWRAM_CODE | 623 | IWRAM_CODE |
614 | void | 624 | void |
615 | flip_buffer(void) { | 625 | flip_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 | // |