summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Bridle <ben@derelict.engineering>2024-11-22 16:04:02 +1300
committerBen Bridle <ben@derelict.engineering>2024-11-22 16:15:11 +1300
commita05dc964313a3f1431b9d08d33afb4daf45c0819 (patch)
tree394074f98f30d7851a82038b1091456446df23c4
parent4f8805869c469cb1b3685e03c3ea34d7654b5cb7 (diff)
downloadbedrock-nds-a05dc964313a3f1431b9d08d33afb4daf45c0819.zip
Update palette only when screen buffers flip
Previously, any palette updates would be immediately visible, but any screen updates would draw to the back buffer and would only become visible when the back buffer was copied to the front buffer. This could result in a flash of a new palette before the new screen had a chance to draw and become visible. To prevent this, a second palette was created to receive palette updates, with the updates only being copied to the visible palette when the screen buffers flip.
-rw-r--r--arm9/source/devices/screen.c28
-rw-r--r--arm9/source/devices/screen.h9
-rw-r--r--arm9/source/main.c21
3 files changed, 36 insertions, 22 deletions
diff --git a/arm9/source/devices/screen.c b/arm9/source/devices/screen.c
index 0d2fc36..5c16d8f 100644
--- a/arm9/source/devices/screen.c
+++ b/arm9/source/devices/screen.c
@@ -19,6 +19,31 @@ a 16-bit tile index (low 10 bits are tile index, then h-flip, then v-flip, then
#include "screen.h"
#include "../bang.h"
+Screen scr_main = {
+ .bgv = BG_TILE_RAM(BG_SLOT_VIS),
+ .fgv = BG_TILE_RAM(FG_SLOT_VIS),
+ .bg = BG_TILE_RAM(BG_SLOT),
+ .fg = BG_TILE_RAM(FG_SLOT),
+ .map = BG_MAP_RAM(MAP_SLOT),
+ .palv = BG_PALETTE,
+};
+Screen scr_sub = {
+ .bgv = BG_TILE_RAM_SUB(BG_SLOT_VIS),
+ .fgv = BG_TILE_RAM_SUB(FG_SLOT_VIS),
+ .bg = BG_TILE_RAM_SUB(BG_SLOT),
+ .fg = BG_TILE_RAM_SUB(FG_SLOT),
+ .map = BG_MAP_RAM_SUB(MAP_SLOT),
+ .palv = BG_PALETTE_SUB,
+};
+
+void scr_make_main(ScreenDevice *scr) {
+ scr->nds = &scr_main;
+}
+
+void scr_make_sub(ScreenDevice *scr) {
+ scr->nds = &scr_sub;
+}
+
void init_screens(void) {
// Allocate VRAM for screens
videoSetMode(DISPLAY_BG0_ACTIVE | DISPLAY_BG1_ACTIVE | MODE_0_2D);
@@ -127,6 +152,9 @@ void erase_screen(Screen *nds) {
void flip_buffer(Screen *nds) {
dmaCopyWords(0, nds->bg, nds->bgv, TILES_MEM);
dmaCopyWords(0, nds->fg, nds->fgv, TILES_MEM);
+ for (int i=0; i<16; i++) {
+ nds->palv[i] = nds->pal[i];
+ }
}
void black_screen(Screen *nds) {
diff --git a/arm9/source/devices/screen.h b/arm9/source/devices/screen.h
index a406051..3e75334 100644
--- a/arm9/source/devices/screen.h
+++ b/arm9/source/devices/screen.h
@@ -25,9 +25,10 @@
typedef struct {
u16 *bgv, *fgv; // visible tile memory
- u16 *bg, *fg; // tile memory
- u16 *map; // tile map
- u16 *pal; // colour palette
+ u16 *bg, *fg; // buffered tile memory
+ u16 *map; // tile map (never changes)
+ u16 *palv; // visible colour palette
+ u16 pal[16]; // buffered colour palette
} Screen;
typedef struct {
@@ -43,6 +44,8 @@
} ScreenDevice;
void init_screens(void);
+ void scr_make_main(ScreenDevice *scr);
+ void scr_make_sub(ScreenDevice *scr);
void set_palette_high(ScreenDevice *scr, u8 high);
void set_palette_low(ScreenDevice *scr, u8 low);
diff --git a/arm9/source/main.c b/arm9/source/main.c
index 8be7837..095e089 100644
--- a/arm9/source/main.c
+++ b/arm9/source/main.c
@@ -37,23 +37,6 @@ void receive_input(void) {
}
-Screen scr_main = {
- .bgv = BG_TILE_RAM(BG_SLOT_VIS),
- .fgv = BG_TILE_RAM(FG_SLOT_VIS),
- .bg = BG_TILE_RAM(BG_SLOT),
- .fg = BG_TILE_RAM(FG_SLOT),
- .map = BG_MAP_RAM(MAP_SLOT),
- .pal = BG_PALETTE,
-};
-Screen scr_sub = {
- .bgv = BG_TILE_RAM_SUB(BG_SLOT_VIS),
- .fgv = BG_TILE_RAM_SUB(FG_SLOT_VIS),
- .bg = BG_TILE_RAM_SUB(BG_SLOT),
- .fg = BG_TILE_RAM_SUB(FG_SLOT),
- .map = BG_MAP_RAM_SUB(MAP_SLOT),
- .pal = BG_PALETTE_SUB,
-};
-
int main(void) {
#define ALIVE(br) (br && br->alive)
#define AWAKE(br) (br && br->alive && br->awake)
@@ -79,8 +62,8 @@ int main(void) {
start_br(&br[1], keyboard_program, sizeof(keyboard_program));
br_main = &br[0];
br_sub = &br[1];
- br_main->scr.nds = &scr_main;
- br_sub->scr.nds = &scr_sub;
+ scr_make_main(&br_main->scr);
+ scr_make_sub(&br_sub->scr);
while (1) {
if (AWAKE(br_main)) run_br(br_main);