summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-04-15 20:54:34 +0200
committerBad Diode <bd@badd10de.dev>2023-04-15 20:54:34 +0200
commite56c4d8e3932db4edfa04312e02fa2be071f93c4 (patch)
treea68cb4f4068bf4037544f47134607d8c9e426efd
parent87e5c991bf866db9253915f403bdb8e30f9d6449 (diff)
downloadgba-link-cable-tester-e56c4d8e3932db4edfa04312e02fa2be071f93c4.tar.gz
gba-link-cable-tester-e56c4d8e3932db4edfa04312e02fa2be071f93c4.zip
Add a 3rd BG to act as a shade while BG register changes
This helps create a double buffering effect but unfortunately due to delays in setting up BG priority, this creates tearing artifacts.
-rw-r--r--src/main.c21
-rw-r--r--src/renderer_m0.c136
2 files changed, 70 insertions, 87 deletions
diff --git a/src/main.c b/src/main.c
index a7bad92..a52ad7c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -119,24 +119,25 @@ int main(void) {
119 // Register interrupts. 119 // Register interrupts.
120 irq_init(); 120 irq_init();
121 irs_set(IRQ_VBLANK, irs_stub); 121 irs_set(IRQ_VBLANK, irs_stub);
122 122 flip_buffer();
123 // Initialize sequencer.
124 // flip_buffer();
125 // screen_fill(1);
126 // screen_fill(2);
127 // backbuf[0] = 0x11111111;
128 // screen_fill(1);
129 // flip_buffer();
130 // screen_fill(2);
131 // flip_buffer();
132 123
133 // Main loop. 124 // Main loop.
134 PROF_INIT(); 125 PROF_INIT();
126 int x = 0;
127 int inc = 1;
135 while (true) { 128 while (true) {
136 bios_vblank_wait(); 129 bios_vblank_wait();
137 130
138 PROF(test_clear(), test_clear_cycles); 131 PROF(test_clear(), test_clear_cycles);
139 // PROF(test_lines(), test_lines_cycles); 132 // PROF(test_lines(), test_lines_cycles);
133 draw_rect(0 + x, 0, 100 + x, 100, 2);
134 x += inc;
135 if (x >= 50) {
136 inc = -8;
137 } else if (x <= 0) {
138 inc = 8;
139 }
140 // draw_rect(50, 10, 200, 110, 1);
140 // PROF(test_rect(), test_rect_cycles); 141 // PROF(test_rect(), test_rect_cycles);
141 // PROF(test_fill_rect(), test_fill_rect_cycles); 142 // PROF(test_fill_rect(), test_fill_rect_cycles);
142 // PROF(test_chr(), test_chr_cycles); 143 // PROF(test_chr(), test_chr_cycles);
diff --git a/src/renderer_m0.c b/src/renderer_m0.c
index 3034d40..b0d4a6e 100644
--- a/src/renderer_m0.c
+++ b/src/renderer_m0.c
@@ -27,8 +27,12 @@
27// Charblock and screenblock for both render buffers. 27// Charblock and screenblock for both render buffers.
28#define CB_0 0 28#define CB_0 0
29#define CB_1 1 29#define CB_1 1
30// NOTE: CB_2 could be at the end of 2 (0x0600:8000) since we only need a clear
31// color tile. Testing at 3 for now.
32#define CB_2 3
30#define SB_0 20 33#define SB_0 20
31#define SB_1 21 34#define SB_1 21
35#define SB_2 23
32 36
33// Available storage for other memory. 37// Available storage for other memory.
34// #define FG_PIXELS ((u32*)(MEM_VRAM + KB(44))) 38// #define FG_PIXELS ((u32*)(MEM_VRAM + KB(44)))
@@ -71,11 +75,11 @@ static u32 *backbuf = BUF_1;
71 75
72IWRAM_CODE 76IWRAM_CODE
73void screen_fill(u8 clr) { 77void screen_fill(u8 clr) {
74#if 0 78#if 1
75// u32 *dst = backbuf; 79 u32 *dst = backbuf;
76// for(int i = 0; i < KB(75) / 8; i++) { 80 for(int i = 0; i < KB(20) / 4; i++) {
77// *dst++ = 0x01010101 * clr; 81 *dst++ = 0x11111111 * clr;
78// } 82 }
79#else 83#else
80 dma_fill(backbuf, 0x11111111 * clr, KB(20), 3); 84 dma_fill(backbuf, 0x11111111 * clr, KB(20), 3);
81#endif 85#endif
@@ -105,7 +109,13 @@ IWRAM_CODE
105static inline 109static inline
106void 110void
107draw_hline(size_t x0, size_t x1, size_t y0, u8 clr) { 111draw_hline(size_t x0, size_t x1, size_t y0, u8 clr) {
108 // TODO 112 BOUNDCHECK_SCREEN(x0, y0);
113 BOUNDCHECK_SCREEN(x1, y0);
114
115 // TODO: perf
116 for (size_t x = x0; x <= x1; x++) {
117 draw_pixel(x, y0, clr);
118 }
109} 119}
110 120
111IWRAM_CODE 121IWRAM_CODE
@@ -113,14 +123,20 @@ UNROLL_LOOPS
113static inline 123static inline
114void 124void
115draw_vline(size_t x0, size_t y0, size_t y1, u8 clr) { 125draw_vline(size_t x0, size_t y0, size_t y1, u8 clr) {
116 // TODO 126 BOUNDCHECK_SCREEN(x0, y0);
127 BOUNDCHECK_SCREEN(x0, y1);
128
129 // TODO: perf
130 for (size_t y = y0; y <= y1; y++) {
131 draw_pixel(x0, y, clr);
132 }
117} 133}
118 134
119IWRAM_CODE 135IWRAM_CODE
120void 136void
121draw_line(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) { 137draw_line(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
122 // BOUNDCHECK_SCREEN(x0, y0); 138 BOUNDCHECK_SCREEN(x0, y0);
123 // BOUNDCHECK_SCREEN(x1, y1); 139 BOUNDCHECK_SCREEN(x1, y1);
124 if (y0 == y1) { 140 if (y0 == y1) {
125 MAYBE_SWAP(x0, x1); 141 MAYBE_SWAP(x0, x1);
126 draw_hline(x0, x1, y0, clr); 142 draw_hline(x0, x1, y0, clr);
@@ -271,51 +287,6 @@ draw_rect(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
271 draw_hline(x0, x1, y1, clr); 287 draw_hline(x0, x1, y1, clr);
272 draw_vline(x0, y0, y1, clr); 288 draw_vline(x0, y0, y1, clr);
273 draw_vline(x1, y0, y1, clr); 289 draw_vline(x1, y0, y1, clr);
274
275 // TODO: check if this is better.
276// BOUNDCHECK_SCREEN(x0, y0);
277// BOUNDCHECK_SCREEN(x1, y1);
278
279// // Find row positions for the given x/y coordinates.
280// size_t tile_x0 = x0 / 8;
281// size_t tile_y0 = y0 / 8;
282// size_t tile_x1 = x1 / 8;
283// size_t tile_y1 = y1 / 8;
284// size_t start_col0 = x0 % 8;
285// size_t start_col1 = x1 % 8;
286// size_t start_row0 = y0 % 8;
287// size_t start_row1 = y1 % 8;
288
289// // Get a pointer to the backbuffer and the tile row.
290// u32 *buf_top = &BACKBUF[start_row0 + (tile_x0 + tile_y0 * 32) * 8];
291// u32 *buf_bot = &BACKBUF[start_row1 + (tile_x0 + tile_y1 * 32) * 8];
292
293// size_t dx = tile_x1 - tile_x0;
294// size_t dy = tile_y1 - tile_y0;
295
296// memset(buf_top, 3, x1 - x0);
297// memset(buf_bot, 3, x1 - x0);
298
299// if (dx < 1) {
300// dirty_tiles[tile_y0] |= 1 << tile_x0;
301// dirty_tiles[tile_y1] |= 1 << tile_x0;
302// } else {
303// dirty_tiles[tile_y0] |= 1 << tile_x0;
304// dirty_tiles[tile_y1] |= 1 << tile_x0;
305// for (size_t i = 1; i < dx; i++) {
306// dirty_tiles[tile_y0] |= 1 << (tile_x0 + i);
307// dirty_tiles[tile_y1] |= 1 << (tile_x0 + i);
308// }
309// dirty_tiles[tile_y0] |= 1 << (tile_x0 + dx);
310// dirty_tiles[tile_y1] |= 1 << (tile_x0 + dx);
311// }
312// if (dy < 1) {
313// } else {
314// for (size_t j = 1; j < dy; j++) {
315// dirty_tiles[tile_y0 + j] |= 1 << tile_x0;
316// dirty_tiles[tile_y0 + j] |= 1 << (tile_x0 + dx);
317// }
318// }
319} 290}
320 291
321IWRAM_CODE 292IWRAM_CODE
@@ -345,21 +316,21 @@ draw_filled_rect(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
345 316
346 // size_t dx = x1 - x0; 317 // size_t dx = x1 - x0;
347 // size_t dy = y1 - y0; 318 // size_t dy = y1 - y0;
348 // u8 *buf = &BACKBUF[0]; 319 // u8 *buf = &backbuf[0];
349 // memset(buf, 0x11 * clr, 16); 320 // memset(buf, 0x11 * clr, 16);
350 //for (size_t j = 0; j < 1; j++) { 321 //for (size_t j = 0; j < 1; j++) {
351 // // for (size_t i = 0; i < dx; i++) { 322 // // for (size_t i = 0; i < dx; i++) {
352 // // buf[i + j * 16] = clr; 323 // // buf[i + j * 16] = clr;
353 // // } 324 // // }
354 // // 325 // //
355 // // BACKBUF[j + 0] = 0x11111111 * clr; 326 // // backbuf[j + 0] = 0x11111111 * clr;
356 // // BACKBUF[j + 1] = 0x11111111 * clr; 327 // // backbuf[j + 1] = 0x11111111 * clr;
357 // // BACKBUF[j + 2] = 0x11111111 * clr; 328 // // backbuf[j + 2] = 0x11111111 * clr;
358 // // BACKBUF[j + 3] = 0x11111111 * clr; 329 // // backbuf[j + 3] = 0x11111111 * clr;
359 // // BACKBUF[j + 4] = 0x11111111 * clr; 330 // // backbuf[j + 4] = 0x11111111 * clr;
360 // // BACKBUF[j + 5] = 0x11111111 * clr; 331 // // backbuf[j + 5] = 0x11111111 * clr;
361 // // BACKBUF[j + 6] = 0x11111111 * clr; 332 // // backbuf[j + 6] = 0x11111111 * clr;
362 // // BACKBUF[j + 7] = 0x11111111 * clr; 333 // // backbuf[j + 7] = 0x11111111 * clr;
363 334
364 // buf[j + 0] = 0x1 * clr; 335 // buf[j + 0] = 0x1 * clr;
365 // buf[j + 1] = 0x1 * clr; 336 // buf[j + 1] = 0x1 * clr;
@@ -370,7 +341,7 @@ draw_filled_rect(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
370 // // buf[j + 6] = 0x1111 * clr; 341 // // buf[j + 6] = 0x1111 * clr;
371 // // buf[j + 7] = 0x1111 * clr; 342 // // buf[j + 7] = 0x1111 * clr;
372 //} 343 //}
373 // u8 *buf = &BACKBUF[0]; 344 // u8 *buf = &backbuf[0];
374 // buf[8 * 16 + 0] = clr; 345 // buf[8 * 16 + 0] = clr;
375 // buf[8 * 16 + 1] = clr; 346 // buf[8 * 16 + 1] = clr;
376 // buf[8 * 16 + 2] = clr; 347 // buf[8 * 16 + 2] = clr;
@@ -404,7 +375,7 @@ draw_filled_rect(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
404 375
405// // Get a pointer to the backbuffer and the tile row. 376// // Get a pointer to the backbuffer and the tile row.
406// size_t pos = start_row + (tile_x + tile_y * 32) * 8; 377// size_t pos = start_row + (tile_x + tile_y * 32) * 8;
407// u32 *backbuffer = &BACKBUF[pos]; 378// u32 *backbuffer = &backbuf[pos];
408// u32 *row = tile; 379// u32 *row = tile;
409 380
410// // This will blend all colors weirdly if using tiles that contain colors 381// // This will blend all colors weirdly if using tiles that contain colors
@@ -474,20 +445,18 @@ void
474flip_buffer(void) { 445flip_buffer(void) {
475 if (backbuf == BUF_0) { 446 if (backbuf == BUF_0) {
476 backbuf = BUF_1; 447 backbuf = BUF_1;
477 DISP_CTRL = DISP_MODE_0 | DISP_BG_1 | DISP_OBJ; 448 BG_CTRL(0) = BG_CHARBLOCK(CB_0) | BG_SCREENBLOCK(SB_0) | BG_PRIORITY(0);
478 BG_CTRL(0) = BG_CHARBLOCK(CB_0) | BG_SCREENBLOCK(SB_0) | BG_PRIORITY(2); 449 BG_CTRL(1) = BG_CHARBLOCK(CB_1) | BG_SCREENBLOCK(SB_1) | BG_PRIORITY(2);
479 BG_CTRL(1) = BG_CHARBLOCK(CB_1) | BG_SCREENBLOCK(SB_1) | BG_PRIORITY(1);
480 } else { 450 } else {
481 backbuf = BUF_0; 451 backbuf = BUF_0;
482 DISP_CTRL = DISP_MODE_0 | DISP_BG_0 | DISP_OBJ; 452 BG_CTRL(0) = BG_CHARBLOCK(CB_0) | BG_SCREENBLOCK(SB_0) | BG_PRIORITY(2);
483 BG_CTRL(0) = BG_CHARBLOCK(CB_0) | BG_SCREENBLOCK(SB_0) | BG_PRIORITY(1); 453 BG_CTRL(1) = BG_CHARBLOCK(CB_1) | BG_SCREENBLOCK(SB_1) | BG_PRIORITY(0);
484 BG_CTRL(1) = BG_CHARBLOCK(CB_1) | BG_SCREENBLOCK(SB_1) | BG_PRIORITY(2);
485 } 454 }
486 // TODO: Copying all tiles for now. Study if it's better to use dirty_tiles 455 // TODO: Copying all tiles for now. Study if it's better to use dirty_tiles
487 // or dirty_lines. 456 // or dirty_lines.
488 // Copy dirty tiles from the backbuffer to the frontbuffer. 457 // Copy dirty tiles from the backbuffer to the frontbuffer.
489 // Tile *dst = FRONTBUF; 458 // Tile *dst = FRONTBUF;
490 // Tile *src = BACKBUF; 459 // Tile *src = backbuf;
491 // for (size_t j = 0; j < 20; ++j) { 460 // for (size_t j = 0; j < 20; ++j) {
492 // // if (dirty_tiles[j] == 0) { 461 // // if (dirty_tiles[j] == 0) {
493 // // continue; 462 // // continue;
@@ -647,30 +616,43 @@ txt_drawc(char c, size_t x, size_t y, u8 clr) {
647void 616void
648renderer_init(void) { 617renderer_init(void) {
649 // Initialize display mode and bg palette. 618 // Initialize display mode and bg palette.
650 DISP_CTRL = DISP_MODE_0 | DISP_BG_0 | DISP_BG_1 | DISP_OBJ; 619 DISP_CTRL = DISP_MODE_0 | DISP_BG_0 | DISP_BG_1 | DISP_BG_2 | DISP_OBJ;
620 // DISP_CTRL = DISP_MODE_0 | DISP_BG_0 | DISP_BG_1 | DISP_OBJ;
621 // TODO: black/grey background to block font/back buffers?
651 622
652 // Clear VRAM. 623 // Clear VRAM.
653 dma_fill(MEM_VRAM, 0, KB(96), 3); 624 dma_fill(MEM_VRAM, 0, KB(96), 3);
654 625
655
656 // Initialize backgrounds. 626 // Initialize backgrounds.
657 BG_CTRL(0) = BG_CHARBLOCK(CB_0) | BG_SCREENBLOCK(SB_0) | BG_PRIORITY(1); 627 BG_CTRL(0) = BG_CHARBLOCK(CB_0) | BG_SCREENBLOCK(SB_0) | BG_PRIORITY(0);
628 BG_CTRL(2) = BG_CHARBLOCK(CB_2) | BG_SCREENBLOCK(SB_2) | BG_PRIORITY(1);
658 BG_CTRL(1) = BG_CHARBLOCK(CB_1) | BG_SCREENBLOCK(SB_1) | BG_PRIORITY(2); 629 BG_CTRL(1) = BG_CHARBLOCK(CB_1) | BG_SCREENBLOCK(SB_1) | BG_PRIORITY(2);
659 630
660 DISP_CTRL = DISP_MODE_0 | DISP_OBJ;
661
662 // Initialize background memory map for frontbuffer. 631 // Initialize background memory map for frontbuffer.
663 // for (size_t i = 0; i < 32 * 20; ++i) { 632 // for (size_t i = 0; i < 32 * 20; ++i) {
664 // TILE_MAP[i] = i; 633 // TILE_MAP[i] = i;
665 // } 634 // }
666 u16 *mem_map_fg = SCREENBLOCK_MEM[SB_0]; 635 u16 *mem_map_fg = SCREENBLOCK_MEM[SB_0];
667 u16 *mem_map_bg = SCREENBLOCK_MEM[SB_1]; 636 u16 *mem_map_bg = SCREENBLOCK_MEM[SB_1];
637 u16 *mem_map_clr = SCREENBLOCK_MEM[SB_2];
668 size_t k = 0; 638 size_t k = 0;
669 for (size_t i = 0; i < 32 * 20; ++i, ++k) { 639 for (size_t i = 0; i < 32 * 20; ++i, ++k) {
670 mem_map_fg[i] = k; 640 mem_map_fg[i] = k;
671 mem_map_bg[i] = k + 32 * 4; 641 mem_map_bg[i] = k + 32 * 4;
642 mem_map_clr[i] = 0;
672 } 643 }
673 644
645 // FIXME: clean this up.
646 u32 *clr_tile =((u32*)(MEM_VRAM) + 0xC000 / 4);
647 clr_tile[0] = 0x22222222;
648 clr_tile[1] = 0x22222222;
649 clr_tile[2] = 0x22222222;
650 clr_tile[3] = 0x22222222;
651 clr_tile[4] = 0x22222222;
652 clr_tile[5] = 0x22222222;
653 clr_tile[6] = 0x22222222;
654 clr_tile[7] = 0x22222222;
655
674 // Initialize default palette. 656 // Initialize default palette.
675 PAL_BUFFER_BG[0] = COLOR_BLACK; 657 PAL_BUFFER_BG[0] = COLOR_BLACK;
676 PAL_BUFFER_BG[1] = COLOR_WHITE; 658 PAL_BUFFER_BG[1] = COLOR_WHITE;