diff --git a/gba/src/4bcanvas.c b/gba/src/4bcanvas.c
index def8b8d..68f4684 100644
--- a/gba/src/4bcanvas.c
+++ b/gba/src/4bcanvas.c
@@ -40,6 +40,17 @@ const TileCanvas screen = {
   .mapBase = se_mat
 };
 
+#ifdef __NDS__
+const TileCanvas screen_sub = {
+  .left = 0, .top = 0, .width = SCREEN_WIDTH >> 3, .height = SCREEN_HEIGHT >> 3,
+  .chrBase = tile_mem_sub[0][0].data,
+  .map = 23,
+  .core = 0,
+  .mapTileBase = 0,
+  .mapBase = se_mat_sub
+};
+#endif
+
 static
 void fillcol(u32 *dst, unsigned int colStride,
              unsigned int l, unsigned int t,
diff --git a/gba/src/4bcanvas.h b/gba/src/4bcanvas.h
index 9814017..8637c28 100644
--- a/gba/src/4bcanvas.h
+++ b/gba/src/4bcanvas.h
@@ -43,6 +43,9 @@ typedef struct TileCanvas {
 } TileCanvas;
 
 extern const TileCanvas screen;
+#ifdef __NDS__
+extern const TileCanvas screen_sub;
+#endif
 
 void canvasClear(const TileCanvas *src, unsigned int color);
 void canvasInit(const TileCanvas *src, unsigned int color);
diff --git a/gba/src/audiosync.c b/gba/src/audiosync.c
index 0fdd361..6d81c31 100644
--- a/gba/src/audiosync.c
+++ b/gba/src/audiosync.c
@@ -88,6 +88,15 @@ void activity_audio_sync() {
       pal_bg_mem[i] = progress >= min_progress[i] ? RGB5(31, 31, 31) : RGB5(0, 0, 0);
     }
     pal_obj_mem[1] = RGB5(31, 31, 31);
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | DCNT_OBJ_1D | DCNT_OBJ | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
+    REG_BG_OFS_SUB[0].x = REG_BG_OFS_SUB[0].y = 0;
+    for (unsigned int i = 0; i < 6; ++i) {
+      pal_bg_mem_sub[i] = progress >= min_progress[i] ? RGB5(31, 31, 31) : RGB5(0, 0, 0);
+    }
+    pal_obj_mem_sub[1] = RGB5(31, 31, 31);
+    #endif
     ppu_copy_oam();
 
     if (progress == 120) {
diff --git a/gba/src/backlight.c b/gba/src/backlight.c
index 75433fc..386b229 100644
--- a/gba/src/backlight.c
+++ b/gba/src/backlight.c
@@ -85,7 +85,14 @@ void activity_backlight_zone(void) {
     VBlankIntrWait();
     pal_bg_mem[0] = inverted ? RGB5(31, 31, 31) : RGB5(0, 0, 0);
     pal_obj_mem[1] = inverted ? RGB5(0, 0, 0): RGB5(31, 31, 31);
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    pal_bg_mem_sub[0] = inverted ? RGB5(31, 31, 31) : RGB5(0, 0, 0);
+    pal_obj_mem_sub[1] = inverted ? RGB5(0, 0, 0): RGB5(31, 31, 31);
+    #endif
     ppu_copy_oam();
     REG_DISPCNT = DCNT_MODE0 | DCNT_OBJ | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_OBJ | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
+    #endif
   }
 }
diff --git a/gba/src/help.c b/gba/src/help.c
index 4af02b2..a4cd3d3 100644
--- a/gba/src/help.c
+++ b/gba/src/help.c
@@ -145,6 +145,16 @@ static void load_help_bg(void) {
   memset16(tile_mem[3][0].data, 0x1111 * FG_BGCOLOR, 16*WINDOW_WIDTH*(PAGE_MAX_USABLE_LINES + 2));
 
   load_bg_to_map(se_mat);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  // Load pattern table
+  LZ77UnCompVram(helpbgtiles_chrTiles, tile_mem_sub[3][TILE_DECOMPRESSED_BASE].data);
+  LZ77UnCompVram(helpsprites_chrTiles, tile_mem_obj_sub[0][CHARACTER_VRAM_BASE].data);
+
+  // Clear VWF canvas
+  memset16(tile_mem_sub[3][0].data, 0x1111 * FG_BGCOLOR, 16*WINDOW_WIDTH*(PAGE_MAX_USABLE_LINES + 2));
+
+  load_bg_to_map(se_mat_sub);
+  #endif
 
   help_bg_loaded = 1;
   help_height = 0;
@@ -192,10 +202,10 @@ static void help_draw_cursor(unsigned int objx) {
   oam_used = ou + 1;
 }
 
-static void help_draw_page(helpdoc_kind doc_num, unsigned int left, unsigned int keymask) {
+static int help_draw_page(helpdoc_kind doc_num, unsigned int left, unsigned int keymask, TILE* target_tile_mem) {
   // Draw document title
-  memset16(tile_mem[3][0].data, FG_BGCOLOR*0x1111, WINDOW_WIDTH * 16);
-  vwf8Puts(tile_mem[3][0].data, helptitles[doc_num], 0, FG_FGCOLOR);
+  memset16(target_tile_mem[0].data, FG_BGCOLOR*0x1111, WINDOW_WIDTH * 16);
+  vwf8Puts(target_tile_mem[0].data, helptitles[doc_num], 0, FG_FGCOLOR);
 
   // Look up the address of the start of this page's text
   help_cur_page = help_wanted_page;
@@ -204,7 +214,7 @@ static void help_draw_page(helpdoc_kind doc_num, unsigned int left, unsigned int
 
   // Draw lines of text to the screen
   while (y < PAGE_FINAL_MAX_LINES) {
-    u32 *dst = tile_mem[3][(y + 1)*WINDOW_WIDTH].data;
+    u32 *dst = target_tile_mem[(y + 1)*WINDOW_WIDTH].data;
     ++y;
     memset16(dst, FG_BGCOLOR*0x1111, WINDOW_WIDTH * 16);
     src = vwf8Puts(dst, src, left, FG_FGCOLOR);
@@ -216,19 +226,18 @@ static void help_draw_page(helpdoc_kind doc_num, unsigned int left, unsigned int
 
   // Clear unused lines that had been used
   for (unsigned int clear_y = y; clear_y < help_height; ++clear_y) {
-    u32 *dst = tile_mem[3][(clear_y + 1)*WINDOW_WIDTH].data;
+    u32 *dst = target_tile_mem[(clear_y + 1)*WINDOW_WIDTH].data;
     memset16(dst, FG_BGCOLOR*0x1111, WINDOW_WIDTH * 16);
   }
 
   // Save how many lines are used and move the cursor up if needed
-  help_height = y;
   if (help_cursor_y >= y) {
     help_cursor_y = y - 1;
   }
 
   // Draw status line depending on size of document and which
   // keys are enabled
-  u32 *dst = tile_mem[3][(PAGE_MAX_USABLE_LINES + 1)*WINDOW_WIDTH].data;
+  u32 *dst = target_tile_mem[(PAGE_MAX_USABLE_LINES + 1)*WINDOW_WIDTH].data;
   memset16(dst, FG_BGCOLOR*0x1111, WINDOW_WIDTH * 16);
 
   if (help_cumul_pages[doc_num + 1] - help_cumul_pages[doc_num] > 1) {
@@ -243,6 +252,8 @@ static void help_draw_page(helpdoc_kind doc_num, unsigned int left, unsigned int
   if (keymask & KEY_B) {
     vwf8Puts(dst, "B: Exit", WINDOW_WIDTH * 8 - 28, FG_FGCOLOR);
   }
+
+  return y;
 }
 
 static const unsigned short bg0_x_sequence[] = {
@@ -298,8 +309,14 @@ unsigned int helpscreen(helpdoc_kind doc_num, unsigned int keymask) {
   // If the help VRAM needs to be reloaded, reload its tiles and map
   if (!help_bg_loaded) {
     REG_DISPCNT = DCNT_BLANK | ACTIVATE_SCREEN_HW;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_DISPCNT_SUB = DCNT_BLANK | ACTIVATE_SCREEN_HW;
+    #endif
     load_help_bg();
     REG_DISPCNT = ACTIVATE_SCREEN_HW;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_DISPCNT_SUB = ACTIVATE_SCREEN_HW;
+    #endif
   } else {
     // If changing pages while BG CHR and map are loaded,
     // schedule an out-load-in sequence and hide the cursor
@@ -322,6 +339,17 @@ unsigned int helpscreen(helpdoc_kind doc_num, unsigned int keymask) {
   REG_BG_OFS[1].x = REG_BG_OFS[1].y = 0;
   REG_BG_OFS[0].x = help_wnd_progress ? WXBASE : 256;
   REG_BG_OFS[0].y = 4;
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  tonccpy(pal_bg_mem_sub+0x00, helpbgtiles_chrPal, sizeof(helpbgtiles_chrPal));
+  tonccpy(pal_obj_mem_sub+0x00, helpsprites_chrPal, sizeof(helpsprites_chrPal));
+
+  // Set up background regs (except DISPCNT)
+  REG_BGCNT_SUB[1] = BG_4BPP|BG_SIZE0|BG_CBB(3)|BG_SBB(BGMAP);
+  REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE1|BG_CBB(3)|BG_SBB(FGMAP);
+  REG_BG_OFS_SUB[1].x = REG_BG_OFS_SUB[1].y = 0;
+  REG_BG_OFS_SUB[0].x = help_wnd_progress ? WXBASE : 256;
+  REG_BG_OFS_SUB[0].y = 4;
+  #endif
   
   // Freeze
   while (1) {
@@ -363,7 +391,11 @@ unsigned int helpscreen(helpdoc_kind doc_num, unsigned int keymask) {
 
     if (help_wnd_progress == 0) {
       help_show_cursor = (keymask & KEY_UP) ? 6 : 0;
-      help_draw_page(doc_num, help_show_cursor, keymask);
+      int final_y = help_draw_page(doc_num, help_show_cursor, keymask, &tile_mem[3][0]);
+      #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+      help_draw_page(doc_num, help_show_cursor, keymask, &tile_mem_sub[3][0]);
+      #endif
+      help_height = final_y;
     }
 
     unsigned int wx = help_move_window();
@@ -376,6 +408,10 @@ unsigned int helpscreen(helpdoc_kind doc_num, unsigned int keymask) {
     VBlankIntrWait();
     REG_DISPCNT = DCNT_MODE0 | DCNT_BG1 | DCNT_BG0 | DCNT_OBJ_1D | DCNT_OBJ | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
     REG_BG_OFS[0].x = wx;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG1 | DCNT_BG0 | DCNT_OBJ_1D | DCNT_OBJ | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
+    REG_BG_OFS_SUB[0].x = wx;
+    #endif
     ppu_copy_oam();
   }
 }
diff --git a/gba/src/megaton.c b/gba/src/megaton.c
index 56436a2..5786dd2 100644
--- a/gba/src/megaton.c
+++ b/gba/src/megaton.c
@@ -140,13 +140,22 @@ void activity_megaton() {
   REG_SOUNDCNT_L = 0xFF77;  // PSG vol/pan
   REG_SOUND1CNT_L = 0x08;   // no sweep
   #endif
+
   dma_memset16(se_mat[PFMAP], BLANK_TILE, 32*(SCREEN_HEIGHT>>3)*2);
-  vwfDrawLabelsPositionBased(megaton_labels, megaton_positions, PFMAP, 0x44);
 
   megaton_draw_static_reticle(se_mat);
   // Make space for results
   dma_memset16(tile_mem[0][0x30].data, 0x0000, 32 * 2 * NUM_TRIALS);
   loadMapRowMajor(&(se_mat[PFMAP][2][2]), 0x30, 2, NUM_TRIALS);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  dma_memset16(se_mat_sub[PFMAP], BLANK_TILE, 32*(SCREEN_HEIGHT>>3)*2);
+
+  megaton_draw_static_reticle(se_mat_sub);
+  // Make space for results
+  dma_memset16(tile_mem_sub[0][0x30].data, 0x0000, 32 * 2 * NUM_TRIALS);
+  loadMapRowMajor(&(se_mat_sub[PFMAP][2][2]), 0x30, 2, NUM_TRIALS);
+  #endif
+  vwfDrawLabelsPositionBased(megaton_labels, megaton_positions, PFMAP, 0x44);
 
   do {
     read_pad_help_check(helpsect_timing_and_reflex_test);
@@ -160,6 +169,9 @@ void activity_megaton() {
       unsigned int early = diff < 0;
       unsigned int value = early ? -diff : diff;
       megaton_print_values(tile_mem[0][0x30 + progress * 2].data, value, early);
+      #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+      megaton_print_values(tile_mem_sub[0][0x30 + progress * 2].data, value, early);
+      #endif
       if (!early && value <= 25) lag[progress++] = value;
     }
     #ifdef __NDS__
@@ -216,9 +228,20 @@ void activity_megaton() {
     pal_bg_mem[0] = (x == 128 && with_audio) ? RGB5(31, 31, 31) : RGB5(0, 0, 0);
     pal_bg_mem[1] = pal_obj_mem[1] = RGB5(31, 31, 31);
     pal_bg_mem[2] = RGB5(20, 25, 31);
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | DCNT_OBJ_1D | DCNT_OBJ | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
+    REG_BG_OFS_SUB[0].x = REG_BG_OFS_SUB[0].y = 0;
+    pal_bg_mem_sub[0] = (x == 128 && with_audio) ? RGB5(31, 31, 31) : RGB5(0, 0, 0);
+    pal_bg_mem_sub[1] = pal_obj_mem_sub[1] = RGB5(31, 31, 31);
+    pal_bg_mem_sub[2] = RGB5(20, 25, 31);
+    #endif
     ppu_copy_oam();
 
     megaton_draw_variable_data(se_mat, y, dir, randomize, with_audio);
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    megaton_draw_variable_data(se_mat_sub, y, dir, randomize, with_audio);
+    #endif
 
     // beep
     #ifdef __NDS__
@@ -244,6 +267,9 @@ void activity_megaton() {
 
   // Display average: First throw away all labels below Y=120
   dma_memset16(se_mat[PFMAP][(SCREEN_HEIGHT - 40)>> 3], BLANK_TILE, 32*4*2);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  dma_memset16(se_mat_sub[PFMAP][(SCREEN_HEIGHT - 40)>> 3], BLANK_TILE, 32*4*2);
+  #endif
 
   unsigned int sum = 0;
   for (unsigned int i = 0; i < NUM_TRIALS; ++i) {
diff --git a/gba/src/motionblur.c b/gba/src/motionblur.c
index 97e7917..b8b24fa 100644
--- a/gba/src/motionblur.c
+++ b/gba/src/motionblur.c
@@ -90,6 +90,11 @@ void activity_motion_blur() {
   dma_memset16(se_mat[PFMAP], BLANK_TILE, 32*(SCREEN_HEIGHT >> 3)*2);
   for (unsigned int y = MOTION_BLUR_START_Y; y < MOTION_BLUR_END_Y; ++y)
     dma_memset16(se_mat[PFMAP][y] + (SCREEN_WIDTH >> 4) - ((MOTION_BLUR_END_Y-MOTION_BLUR_START_Y)/2), 0x0A, (MOTION_BLUR_END_Y-MOTION_BLUR_START_Y)*2);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  dma_memset16(se_mat_sub[PFMAP], BLANK_TILE, 32*(SCREEN_HEIGHT >> 3)*2);
+  for (unsigned int y = MOTION_BLUR_START_Y; y < MOTION_BLUR_END_Y; ++y)
+    dma_memset16(se_mat_sub[PFMAP][y] + (SCREEN_WIDTH >> 4) - ((MOTION_BLUR_END_Y-MOTION_BLUR_START_Y)/2), 0x0A, (MOTION_BLUR_END_Y-MOTION_BLUR_START_Y)*2);
+  #endif
   vwfDrawLabelsPositionBased(motion_blur_labels, motion_blur_positions, PFMAP, 0x20);
   
   unsigned int y = 0;
@@ -139,5 +144,14 @@ void activity_motion_blur() {
     }
     draw_motion_blur_values(se_mat, y, params);
     REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
+    REG_BG_OFS_SUB[0].x = REG_BG_OFS_SUB[0].y = 0;
+    for (unsigned int i = 0; i < 4; ++i) {
+      pal_bg_mem_sub[i] = RGB5(1, 1, 1) * bgc1[i];
+    }
+    draw_motion_blur_values(se_mat_sub, y, params);
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #endif
   } while (!(new_keys & KEY_B));
 }
diff --git a/gba/src/overscan.c b/gba/src/overscan.c
index 899c5b6..bfc16ea 100644
--- a/gba/src/overscan.c
+++ b/gba/src/overscan.c
@@ -80,6 +80,13 @@ void activity_overscan() {
     *c |= 0x44444444;
   }
   dma_memset16(se_mat[PFMAP], 0x0004, 32*(SCREEN_HEIGHT >> 3)*2);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  // Make all BG tiles opaque
+  for (u32 *c = tile_mem_sub[0][0].data; c < tile_mem_sub[0][32].data; ++c) {
+    *c |= 0x44444444;
+  }
+  dma_memset16(se_mat_sub[PFMAP], 0x0004, 32*(SCREEN_HEIGHT >> 3)*2);
+  #endif
 
   while (1) {
     read_pad_help_check(helpsect_overscan);
@@ -119,10 +126,19 @@ void activity_overscan() {
     }
     REG_BGCNT[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
     REG_BG_OFS[0].x = REG_BG_OFS[0].y = 0;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    // Color 0: outside
+    pal_bg_mem_sub[0] = pal_bg_mem_sub[5] = inverted ? RGB5(0, 0, 0) : RGB5(31, 31, 31);
+    pal_bg_mem_sub[4] = inverted ? RGB5(23, 23, 23) : RGB5(15, 15, 15);
+    if (cur_keys & KEY_A) {
+      pal_obj_mem_sub[2] = inverted ? RGB5(31, 31, 31) : RGB5(0, 0, 0);
+    } else {
+      pal_obj_mem_sub[2] = inverted ? RGB5(15, 15, 15) : RGB5(23, 23, 23);
+    }
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
+    REG_BG_OFS_SUB[0].x = REG_BG_OFS_SUB[0].y = 0;
+    #endif
     ppu_copy_oam();
-    REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | DCNT_OBJ_1D | DCNT_OBJ | DCNT_WIN0 | DCNT_WIN1 | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
-    REG_WINOUT = 0x10;  // BG0 inside, BG1 outside
-    REG_WININ = 0x1111;
 
     // start<<8 | end
     // Do this with the y value to fix an NDS bug.
@@ -131,6 +147,10 @@ void activity_overscan() {
     unsigned int y_set_value = (7 << 8) | ((SCREEN_HEIGHT - dist[3]) & 0xFF);
     if(dist[2] == 0)
         y_set_value = ((SCREEN_HEIGHT - dist[3]) & 0xFF);
+
+    REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | DCNT_OBJ_1D | DCNT_OBJ | DCNT_WIN0 | DCNT_WIN1 | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
+    REG_WINOUT = 0x10;  // BG0 inside, BG1 outside
+    REG_WININ = 0x1111;
     
     REG_WIN0H = (dist[1] << 8) | (SCREEN_WIDTH / 2);
     REG_WIN0V = y_set_value;
@@ -147,6 +167,23 @@ void activity_overscan() {
     #endif
     REG_DMA0DAD = (intptr_t)&(REG_WIN0V);
     REG_DMA0CNT = 1|DMA_DST_FIXED|DMA_SRC_FIXED|DMA_32|DMA_AT_HBLANK|DMA_ENABLE;
+
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | DCNT_OBJ_1D | DCNT_OBJ | DCNT_WIN0 | DCNT_WIN1 | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
+    REG_WINOUT_SUB = 0x10;  // BG0 inside, BG1 outside
+    REG_WININ_SUB = 0x1111;
+    
+    REG_WIN0H_SUB = (dist[1] << 8) | (SCREEN_WIDTH / 2);
+    REG_WIN0V_SUB = y_set_value;
+    // NDS requires two windows to fill 256 pixels on the X axys
+    REG_WIN1H_SUB = ((SCREEN_WIDTH / 2) << 8) | ((SCREEN_WIDTH - dist[0]) & 0xFF);
+    REG_WIN1V_SUB = y_set_value;
+  
+    REG_DMA1CNT = 0;
+    REG_DMA1SAD = (intptr_t)&(DMA_FILL(0));
+    REG_DMA1DAD = (intptr_t)&(REG_WIN0V_SUB);
+    REG_DMA1CNT = 1|DMA_DST_FIXED|DMA_SRC_FIXED|DMA_32|DMA_AT_HBLANK|DMA_ENABLE;
+    #endif
     
     for (int i = 0; i < 4; ++i) {
       unsigned int x = overscan_dist_x[i];
@@ -157,6 +194,12 @@ void activity_overscan() {
       se_mat[PFMAP][y][x + 1] = 0x0010 + (value - tens * 10);
       se_mat[PFMAP][y + 1][x] = 0x0006;
       se_mat[PFMAP][y + 1][x + 1] = 0x0007;
+      #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+      se_mat_sub[PFMAP][y][x] = tens ? (0x0010 + tens) : 0x0004;
+      se_mat_sub[PFMAP][y][x + 1] = 0x0010 + (value - tens * 10);
+      se_mat_sub[PFMAP][y + 1][x] = 0x0006;
+      se_mat_sub[PFMAP][y + 1][x + 1] = 0x0007;
+      #endif
     }
   }
 
diff --git a/gba/src/placeholder.c b/gba/src/placeholder.c
index e3af9d2..42c1264 100644
--- a/gba/src/placeholder.c
+++ b/gba/src/placeholder.c
@@ -41,6 +41,9 @@ unsigned short player_facing = 0;
 
 static void load_player(void) {
   LZ77UnCompVram(spritegfx_chrTiles, &(tile_mem_obj[0][16].data));
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  LZ77UnCompVram(spritegfx_chrTiles, &(tile_mem_obj_sub[0][16].data));
+  #endif
   player_x = 56 << 8;
   player_dx = player_frame = player_facing = 0;
 }
@@ -132,14 +135,26 @@ static void put1block(unsigned int x, unsigned int y) {
   se_mat[PFMAP][y][x+1]   = 13 | 0x0000;
   se_mat[PFMAP][y+1][x]   = 14 | 0x0000;
   se_mat[PFMAP][y+1][x+1] = 15 | 0x0000;
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  se_mat_sub[PFMAP][y][x]     = 12 | 0x0000;
+  se_mat_sub[PFMAP][y][x+1]   = 13 | 0x0000;
+  se_mat_sub[PFMAP][y+1][x]   = 14 | 0x0000;
+  se_mat_sub[PFMAP][y+1][x+1] = 15 | 0x0000;
+  #endif
 }
 
 void load_common_bg_tiles(void) {
   bitunpack2(&(tile_mem[0][0].data), bggfx_chrTiles, sizeof(bggfx_chrTiles));
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  bitunpack2(&(tile_mem_sub[0][0].data), bggfx_chrTiles, sizeof(bggfx_chrTiles));
+  #endif
 }
 
 void load_common_obj_tiles(void) {
   bitunpack2(&(tile_mem_obj[0][0].data), bggfx_chrTiles, sizeof(bggfx_chrTiles));
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  bitunpack2(&(tile_mem_obj_sub[0][0].data), bggfx_chrTiles, sizeof(bggfx_chrTiles));
+  #endif
 }
 
 static void draw_bg(void) {
@@ -148,6 +163,11 @@ static void draw_bg(void) {
   memset16(se_mat[PFMAP][0], 0x0004, 32*((SCREEN_HEIGHT >> 3) - 2));
   memset16(se_mat[PFMAP][(SCREEN_HEIGHT >> 3) - 2], 11 | 0x1000, SCREEN_WIDTH >> 3);
   memset16(se_mat[PFMAP][(SCREEN_HEIGHT >> 3) - 1], 1 | 0x1000, SCREEN_WIDTH >> 3);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  memset16(se_mat_sub[PFMAP][0], 0x0004, 32*((SCREEN_HEIGHT >> 3) - 2));
+  memset16(se_mat_sub[PFMAP][(SCREEN_HEIGHT >> 3) - 2], 11 | 0x1000, SCREEN_WIDTH >> 3);
+  memset16(se_mat_sub[PFMAP][(SCREEN_HEIGHT >> 3) - 1], 1 | 0x1000, SCREEN_WIDTH >> 3);
+  #endif
   put1block(2, (SCREEN_HEIGHT >> 3) - 6);
   put1block(2, (SCREEN_HEIGHT >> 3) - 4);
   put1block((SCREEN_WIDTH >> 3) - 4, (SCREEN_HEIGHT >> 3) - 6);
@@ -167,9 +187,15 @@ static void draw_bg(void) {
 void lame_boy_demo(void) {
   // Forced blanking
   REG_DISPCNT = DCNT_BLANK | ACTIVATE_SCREEN_HW;
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  REG_DISPCNT_SUB = DCNT_BLANK | ACTIVATE_SCREEN_HW;
+  #endif
   draw_bg();
   load_player();
   REG_DISPCNT = ACTIVATE_SCREEN_HW;
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  REG_DISPCNT_SUB = ACTIVATE_SCREEN_HW;
+  #endif
 
   // Freeze
   do {
@@ -187,6 +213,14 @@ void lame_boy_demo(void) {
     tonccpy(pal_bg_mem+0x00, bgcolors00, sizeof(bgcolors00));
     tonccpy(pal_bg_mem+0x10, bgcolors10, sizeof(bgcolors10));
     tonccpy(pal_obj_mem+0x00, spritegfx_chrPal, sizeof(spritegfx_chrPal));
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | DCNT_OBJ_1D | DCNT_OBJ | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
+    REG_BG_OFS_SUB[0].x = REG_BG_OFS_SUB[0].y = 0;
+    tonccpy(pal_bg_mem_sub+0x00, bgcolors00, sizeof(bgcolors00));
+    tonccpy(pal_bg_mem_sub+0x10, bgcolors10, sizeof(bgcolors10));
+    tonccpy(pal_obj_mem_sub+0x00, spritegfx_chrPal, sizeof(spritegfx_chrPal));
+    #endif
     ppu_copy_oam();
   } while (!(new_keys & KEY_B));
 }
diff --git a/gba/src/ppuclear.c b/gba/src/ppuclear.c
index fd19cb7..4015a5d 100644
--- a/gba/src/ppuclear.c
+++ b/gba/src/ppuclear.c
@@ -71,6 +71,9 @@ void ppu_copy_oam() {
   CP15_CleanAndFlushDCache();
   #endif
   tonccpy(oam_mem, SOAM, sizeof(SOAM));
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  tonccpy(oam_mem_sub, SOAM, sizeof(SOAM));
+  #endif
 }
 
 void dma_memset16(void *dst, unsigned int c16, size_t length_bytes) {
diff --git a/gba/src/scrolltest.c b/gba/src/scrolltest.c
index 5c16314..f92ef0d 100644
--- a/gba/src/scrolltest.c
+++ b/gba/src/scrolltest.c
@@ -41,6 +41,10 @@ void activity_grid_scroll(void) {
 
   load_common_bg_tiles();
   dma_memset16(se_mat[PFSCROLLTEST], 0x0020, 32*32*2);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  dma_memset16(se_mat_sub[PFSCROLLTEST], 0x0020, 32*32*2);
+  #endif
+
   do {
     read_pad_help_check(helpsect_grid_scroll_test);
     held_keys |= new_keys;
@@ -85,6 +89,14 @@ void activity_grid_scroll(void) {
     pal_bg_mem[0] = inverted ? RGB5(31,31,31) : RGB5(0, 0, 0);
     pal_bg_mem[1] = inverted ? RGB5(0, 0, 0) : RGB5(31,31,31);
     REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFSCROLLTEST);
+    REG_BG_OFS_SUB[0].x = x;
+    REG_BG_OFS_SUB[0].y = y;
+    pal_bg_mem_sub[0] = inverted ? RGB5(31,31,31) : RGB5(0, 0, 0);
+    pal_bg_mem_sub[1] = inverted ? RGB5(0, 0, 0) : RGB5(31,31,31);
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #endif
   } while (!(new_keys & KEY_B));
 }
 
@@ -149,8 +161,15 @@ static const unsigned short kikipalette1[] = {
 static void load_kiki_bg(void) {
   bitunpack2(tile_mem[0][0].data, kikitiles_chrTiles, sizeof(kikitiles_chrTiles));
   dma_memset16(se_mat[PFSCROLLTEST], 0x0000, 32*64*2);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  bitunpack2(tile_mem_sub[0][0].data, kikitiles_chrTiles, sizeof(kikitiles_chrTiles));
+  dma_memset16(se_mat_sub[PFSCROLLTEST], 0x0000, 32*64*2);
+  #endif
+
+  char metatile_buffer[16];
+  for(int i = 0; i < 16; i++)
+    metatile_buffer[i] = 0; // Clear metatile buffer
 
-  dma_memset16(help_line_buffer, 0x0000, 16);  // Clear metatile buffer
   for (unsigned int y = 0; y < 32; ++y) {
     // Decode one row
     unsigned int tiletotopleft = 0;
@@ -158,7 +177,7 @@ static void load_kiki_bg(void) {
 
     // Run Markov chain: guess the most common tile below each
     for (unsigned int x = 0; x < 16; x++) {
-      unsigned int tilethere = help_line_buffer[x];
+      unsigned int tilethere = metatile_buffer[x];
       if (tiletoleft == 3) {
         // To the right of a wall, different rules apply
         tiletoleft = mt_belowR[tilethere];
@@ -169,25 +188,31 @@ static void load_kiki_bg(void) {
         }
       }
       tiletotopleft = tilethere;
-      help_line_buffer[x] = tiletoleft;
+      metatile_buffer[x] = tiletoleft;
     }
     
     // Replace with path from replaceloop
     unsigned int wallbits = kikimap_chrTiles[y];
     for (unsigned int x = 0; x < 16 && wallbits; ++x) {
       unsigned int replacement = wallbits & 0x03;
-      if (replacement) help_line_buffer[x] = replacement;
+      if (replacement) metatile_buffer[x] = replacement;
       wallbits >>= 2;
     }
 
     // Render metatile row
     for (unsigned int x = 0; x < 16; ++x) {
-      unsigned int mtid = help_line_buffer[x];
+      unsigned int mtid = metatile_buffer[x];
       unsigned int attr = (mtid >= 1 && mtid <= 3) ? 0x1000 : 0x0000;
       se_mat[PFSCROLLTEST][y * 2    ][x * 2    ] = metatiles[mtid][0] | attr;
       se_mat[PFSCROLLTEST][y * 2    ][x * 2 + 1] = metatiles[mtid][1] | attr;
       se_mat[PFSCROLLTEST][y * 2 + 1][x * 2    ] = metatiles[mtid][2] | attr;
       se_mat[PFSCROLLTEST][y * 2 + 1][x * 2 + 1] = metatiles[mtid][3] | attr;
+      #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+      se_mat_sub[PFSCROLLTEST][y * 2    ][x * 2    ] = metatiles[mtid][0] | attr;
+      se_mat_sub[PFSCROLLTEST][y * 2    ][x * 2 + 1] = metatiles[mtid][1] | attr;
+      se_mat_sub[PFSCROLLTEST][y * 2 + 1][x * 2    ] = metatiles[mtid][2] | attr;
+      se_mat_sub[PFSCROLLTEST][y * 2 + 1][x * 2 + 1] = metatiles[mtid][3] | attr;
+      #endif
     }
   }
   // This map is a PITA to load because of the compression implied
@@ -207,9 +232,20 @@ void activity_kiki_scroll(void) {
     REG_BG_OFS[0].y = scrolltest_y >> 1;
     REG_BG_OFS[0].x = (256 - SCREEN_WIDTH) / 2;
     REG_BG_OFS[1].x = REG_BG_OFS[1].y = 0;
-    REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
     tonccpy(pal_bg_mem+0, kikipalette0, sizeof(kikipalette0));
     tonccpy(pal_bg_mem+16, kikipalette1, sizeof(kikipalette1));
+    pal_bg_mem[241] = 0;
+    REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE2|BG_CBB(0)|BG_SBB(PFSCROLLTEST);
+    REG_BG_OFS_SUB[0].y = scrolltest_y >> 1;
+    REG_BG_OFS_SUB[0].x = (256 - SCREEN_WIDTH) / 2;
+    REG_BG_OFS_SUB[1].x = REG_BG_OFS_SUB[1].y = 0;
+    tonccpy(pal_bg_mem_sub+0, kikipalette0, sizeof(kikipalette0));
+    tonccpy(pal_bg_mem_sub+16, kikipalette1, sizeof(kikipalette1));
+    pal_bg_mem_sub[241] = 0;
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #endif
   } while (!(new_keys & KEY_B));
 }
 
@@ -218,6 +254,10 @@ void activity_kiki_scroll(void) {
 void hill_zone_load_bg(void) {
   LZ77UnCompVram(greenhillzone_chrTiles, tile_mem[0][0].data);
   LZ77UnCompVram(greenhillzone_chrMap, se_mat[PFSCROLLTEST]);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  LZ77UnCompVram(greenhillzone_chrTiles, tile_mem_sub[0][0].data);
+  LZ77UnCompVram(greenhillzone_chrMap, se_mat_sub[PFSCROLLTEST]);
+  #endif
 }
 
 #ifdef __NDS__
@@ -233,6 +273,11 @@ static void __hill_zone_set_scroll(uint16_t *hdmaTable, unsigned int x, bool rel
     REG_BGCNT[1] = BG_4BPP|BG_SIZE1|BG_CBB(0)|BG_SBB(PFSCROLLTEST);
     tonccpy(pal_bg_mem+0, greenhillzone_chrPal, sizeof(greenhillzone_chrPal));
     pal_bg_mem[241] = 0;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_BGCNT_SUB[1] = BG_4BPP|BG_SIZE1|BG_CBB(0)|BG_SBB(PFSCROLLTEST);
+    tonccpy(pal_bg_mem_sub+0, greenhillzone_chrPal, sizeof(greenhillzone_chrPal));
+    pal_bg_mem_sub[241] = 0;
+    #endif
   }
 
   // Because libgba's ISR takes so long, we're already out of hblank
@@ -249,6 +294,13 @@ static void __hill_zone_set_scroll(uint16_t *hdmaTable, unsigned int x, bool rel
   REG_DMA0DAD = (intptr_t)&(REG_BG_OFS[1].x);
   REG_DMA0CNT = 1|DMA_DST_RELOAD|DMA_SRC_INC|DMA_REPEAT|DMA_16|DMA_AT_HBLANK|DMA_ENABLE;
   REG_BG_OFS[1].x = hdmaTable[0];
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  REG_DMA1CNT = 0;
+  REG_DMA1SAD = (intptr_t)&(hdmaTable[1]);
+  REG_DMA1DAD = (intptr_t)&(REG_BG_OFS_SUB[1].x);
+  REG_DMA1CNT = 1|DMA_DST_RELOAD|DMA_SRC_INC|DMA_REPEAT|DMA_16|DMA_AT_HBLANK|DMA_ENABLE;
+  REG_BG_OFS_SUB[1].x = hdmaTable[0];
+  #endif
 }
 
 // Parallax scrolling for hill zone
@@ -278,8 +330,14 @@ void activity_hill_zone_scroll(void) {
 
     VBlankIntrWait();
     REG_DISPCNT = DCNT_MODE0 | DCNT_BG1 | ACTIVATE_SCREEN_HW;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG1 | ACTIVATE_SCREEN_HW;
+    #endif
     __hill_zone_set_scroll(hdmaTable, selected_scrolltest_y, reload);
   } while (!(new_keys & KEY_B));
   REG_DMA0CNT = 0;
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  REG_DMA1CNT = 0;
+  #endif
 }
 
diff --git a/gba/src/shadowsprite.c b/gba/src/shadowsprite.c
index 906543c..90456d0 100644
--- a/gba/src/shadowsprite.c
+++ b/gba/src/shadowsprite.c
@@ -31,6 +31,11 @@ static void gus_bg_setup(void) {
   LZ77UnCompVram(Gus_portrait_chrTiles, tile_mem[0][0].data);
   dma_memset16(se_mat[PFSCROLLTEST], 0x0000, 32*(SCREEN_HEIGHT >> 3)*2);
   load_flat_map(&(se_mat[PFSCROLLTEST][0][8]), Gus_portrait_chrMap, 14, SCREEN_HEIGHT >> 3);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  LZ77UnCompVram(Gus_portrait_chrTiles, tile_mem_sub[0][0].data);
+  dma_memset16(se_mat_sub[PFSCROLLTEST], 0x0000, 32*(SCREEN_HEIGHT >> 3)*2);
+  load_flat_map(&(se_mat_sub[PFSCROLLTEST][0][8]), Gus_portrait_chrMap, 14, SCREEN_HEIGHT >> 3);
+  #endif
 }
 
 static void gus_bg_set_scroll(uint16_t *hdmaTable, unsigned int unused) {
@@ -40,12 +45,23 @@ static void gus_bg_set_scroll(uint16_t *hdmaTable, unsigned int unused) {
   REG_BG_OFS[1].x = 0;
   REG_BG_OFS[1].y = 0;
   tonccpy(pal_bg_mem, Gus_portrait_chrPal, sizeof(Gus_portrait_chrPal));
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  REG_BGCNT_SUB[1] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFSCROLLTEST);
+  REG_BG_OFS_SUB[1].x = 0;
+  REG_BG_OFS_SUB[1].y = 0;
+  tonccpy(pal_bg_mem_sub, Gus_portrait_chrPal, sizeof(Gus_portrait_chrPal));
+  #endif
 }
 
 static void donna_bg_setup(void) {
   LZ77UnCompVram(Donna_chrTiles, tile_mem[0][0].data);
   dma_memset16(se_mat[PFSCROLLTEST], 0x0000, 32*(SCREEN_HEIGHT >> 3)*2);
   load_flat_map(&(se_mat[PFSCROLLTEST][0][0]), Donna_chrMap, (SCREEN_WIDTH >> 3), (SCREEN_HEIGHT >> 3));
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  tonccpy(tile_mem_sub[0][0].data, tile_mem[0][0].data, ((const int*)Donna_chrTiles)[0]>>8);
+  dma_memset16(se_mat_sub[PFSCROLLTEST], 0x0000, 32*(SCREEN_HEIGHT >> 3)*2);
+  load_flat_map(&(se_mat_sub[PFSCROLLTEST][0][0]), Donna_chrMap, (SCREEN_WIDTH >> 3), (SCREEN_HEIGHT >> 3));
+  #endif
 }
 
 #ifdef __NDS__
@@ -61,11 +77,20 @@ static void donna_bg_set_scroll(uint16_t *hdmaTable, unsigned int unused) {
   REG_BG_OFS[1].x = 0;
   REG_BG_OFS[1].y = 0;
   tonccpy(pal_bg_mem, Donna_chrPal, sizeof(Donna_chrPal));
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  REG_BGCNT_SUB[1] = DONNA_BG_COLORS|BG_SIZE0|BG_CBB(0)|BG_SBB(PFSCROLLTEST);
+  REG_BG_OFS_SUB[1].x = 0;
+  REG_BG_OFS_SUB[1].y = 0;
+  tonccpy(pal_bg_mem_sub, Donna_chrPal, sizeof(Donna_chrPal));
+  #endif
 }
 
 static void striped_bg_setup(unsigned int tilenum) {
   load_common_bg_tiles();
   dma_memset16(se_mat[PFSCROLLTEST], tilenum, 32*(SCREEN_HEIGHT >> 3)*2);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  dma_memset16(se_mat_sub[PFSCROLLTEST], tilenum, 32*(SCREEN_HEIGHT >> 3)*2);
+  #endif
 }
 
 static void bg_2_setup() {
@@ -84,6 +109,13 @@ static void striped_bg_set_scroll(uint16_t *hdmaTable, unsigned int unused) {
   REG_BG_OFS[1].y = 0;
   pal_bg_mem[0] = pal_bg_mem[2] = 0;
   pal_bg_mem[3] = RGB5(31, 31, 31);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  REG_BGCNT_SUB[1] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFSCROLLTEST);
+  REG_BG_OFS_SUB[1].x = 0;
+  REG_BG_OFS_SUB[1].y = 0;
+  pal_bg_mem_sub[0] = pal_bg_mem_sub[2] = 0;
+  pal_bg_mem_sub[3] = RGB5(31, 31, 31);
+  #endif
 }
 
 typedef struct ShadowSpriteBG {
@@ -118,6 +150,10 @@ static const char *const shadow_sprite_types[] = {
 static void shadow_sprite_message(const char *s) {
   dma_memset16(tile_mem[2][1].data, 0x2222, 32*8);
   vwf8Puts(tile_mem[2][1].data, s, 3, 1);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  dma_memset16(tile_mem_sub[2][1].data, 0x2222, 32*8);
+  vwf8Puts(tile_mem_sub[2][1].data, s, 3, 1);
+  #endif
 }
 
 static const unsigned char shadowmasks[3][2] = {
@@ -154,6 +190,14 @@ void activity_shadow_sprite() {
   dma_memset16(tile_mem[2][1].data, 0x2222, 32*8);
 
   load_shadow_sprite(&tile_mem_obj[0][0]);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  dma_memset16(se_mat_sub[PFOVERLAY], 0xF000, 32*((SCREEN_HEIGHT >> 3)+1)*2);
+  loadMapRowMajor(&(se_mat_sub[PFOVERLAY][SCREEN_HEIGHT >> 3][(SCREEN_WIDTH >> 3) - 8]), 0xF001, 8, 1);
+  dma_memset16(tile_mem_sub[2][0].data, 0x0000, 32*1);
+  dma_memset16(tile_mem_sub[2][1].data, 0x2222, 32*8);
+
+  load_shadow_sprite(&tile_mem_obj_sub[0][0]);
+  #endif
   
   bgtypes[cur_bg].setup();
 
@@ -170,12 +214,18 @@ void activity_shadow_sprite() {
       if (new_keys & KEY_RIGHT) {
         if (++cur_bg >= NUM_BGTYPES) cur_bg = 0;
         REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | DCNT_OBJ_1D | DCNT_OBJ | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
+        #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+        REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | DCNT_OBJ_1D | DCNT_OBJ | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
+        #endif
         bgtypes[cur_bg].setup();
         held_keys &= ~KEY_A;
       }
       if (new_keys & KEY_LEFT) {
         cur_bg = cur_bg ? cur_bg - 1 : NUM_BGTYPES - 1;
         REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | DCNT_OBJ_1D | DCNT_OBJ | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
+        #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+        REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | DCNT_OBJ_1D | DCNT_OBJ | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
+        #endif
         bgtypes[cur_bg].setup();
         held_keys &= ~KEY_A;
       }
@@ -252,10 +302,27 @@ void activity_shadow_sprite() {
       }
     }
     REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | DCNT_BG1 | DCNT_OBJ_1D | DCNT_OBJ | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_DMA1CNT = 0;
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE0|BG_CBB(2)|BG_SBB(PFOVERLAY);
+    REG_BG_OFS_SUB[0].x = 0;
+    REG_BG_OFS_SUB[0].y = (changetimeout > 8) ? 8 : changetimeout;
+    pal_bg_mem_sub[241] = RGB5(31, 31, 31);
+    pal_bg_mem_sub[242] = RGB5(0, 0, 0);
+    for (unsigned int y = 0; y < 3; ++y) {
+      for (unsigned int x = 0; x < 3; ++x) {
+        pal_obj_mem_sub[y * 16 + x + 1] = shadow_sprite_palettes[y][x];
+      }
+    }
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | DCNT_BG1 | DCNT_OBJ_1D | DCNT_OBJ | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
+    #endif
     ppu_copy_oam();
     bgtypes[cur_bg].set_scroll(hdmaTable, x * 4);
   } while (!(new_keys & KEY_B));
 
   // clean up after hill zone
   REG_DMA0CNT = 0;
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  REG_DMA1CNT = 0;
+  #endif
 }
diff --git a/gba/src/soundtest.c b/gba/src/soundtest.c
index 9814ae1..ac6a7f5 100644
--- a/gba/src/soundtest.c
+++ b/gba/src/soundtest.c
@@ -56,13 +56,18 @@ const unsigned char waveram_sin16x[16] __attribute__((aligned (2))) = {
 };
 #endif
 
-static void wait24() {
-  ((volatile u16 *)pal_bg_mem)[6] = RGB5(31, 0, 0);
+static void wait24(void) {
+  pal_bg_mem[6] = RGB5(31, 0, 0);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  pal_bg_mem_sub[6] = RGB5(31, 0, 0);
+  #endif
   for (unsigned int i = 24; i > 0; --i) {
     VBlankIntrWait();
-    dma_memset16(pal_bg_mem + 6, RGB5(31, 0, 0), 2);
   }
   pal_bg_mem[6] = RGB5(31, 31, 31);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  pal_bg_mem_sub[6] = RGB5(31, 31, 31);
+  #endif
 }
 
 #ifndef __NDS__
diff --git a/gba/src/stills.c b/gba/src/stills.c
index 94e34a7..264af30 100644
--- a/gba/src/stills.c
+++ b/gba/src/stills.c
@@ -120,6 +120,10 @@ void activity_monoscope(void) {
 
   bitunpack2(tile_mem[0][0].data, monoscope_chrTiles, sizeof(monoscope_chrTiles));
   RLUnCompVram(monoscope_chrMap, se_mat[PFMAP]);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  bitunpack2(tile_mem_sub[0][0].data, monoscope_chrTiles, sizeof(monoscope_chrTiles));
+  RLUnCompVram(monoscope_chrMap, se_mat_sub[PFMAP]);
+  #endif
 
   while (1) {
     read_pad_help_check(helpsect_monoscope);
@@ -140,6 +144,14 @@ void activity_monoscope(void) {
     pal_bg_mem[1] = monoscope_whites[brightness];
     pal_bg_mem[2] = RGB5(31, 0, 0);
     REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
+    REG_BG_OFS_SUB[0].x = REG_BG_OFS_SUB[0].y = 0;
+    pal_bg_mem_sub[0] = (brightness >= 4) ? RGB5(13,13,13) : 0;
+    pal_bg_mem_sub[1] = monoscope_whites[brightness];
+    pal_bg_mem_sub[2] = RGB5(31, 0, 0);
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #endif
   }
 }
 
@@ -153,6 +165,12 @@ void activity_sharpness(void) {
   RLUnCompVram(sharpness_chrMap, se_mat[PFMAP]);
   tonccpy(tile_mem[0][TILE_SHARPNESS_BRICK_POSITION].data, brickstile, sizeof(brickstile));
   dma_memset16(se_mat[PFOVERLAY], 0x0400 | TILE_SHARPNESS_BRICK_POSITION, 32*(SCREEN_HEIGHT>>3)*2);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  bitunpack2(tile_mem_sub[0][0].data, sharpness_chrTiles, sizeof(sharpness_chrTiles));
+  RLUnCompVram(sharpness_chrMap, se_mat_sub[PFMAP]);
+  tonccpy(tile_mem_sub[0][TILE_SHARPNESS_BRICK_POSITION].data, brickstile, sizeof(brickstile));
+  dma_memset16(se_mat_sub[PFOVERLAY], 0x0400 | TILE_SHARPNESS_BRICK_POSITION, 32*(SCREEN_HEIGHT>>3)*2);
+  #endif
 
   while (1) {
     read_pad_help_check(helpsect_sharpness);
@@ -167,13 +185,20 @@ void activity_sharpness(void) {
     }
 
     VBlankIntrWait();
+    const unsigned short *palsrc = inverted ? invgray4pal : gray4pal;
+    if (is_bricks) palsrc = brickspal;
     REG_BGCNT[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)
                 |BG_SBB(is_bricks ? PFOVERLAY : PFMAP);
     REG_BG_OFS[0].x = REG_BG_OFS[0].y = 0;
-    const unsigned short *palsrc = inverted ? invgray4pal : gray4pal;
-    if (is_bricks) palsrc = brickspal;
     tonccpy(pal_bg_mem+0x00, palsrc, sizeof(gray4pal));
     REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)
+                |BG_SBB(is_bricks ? PFOVERLAY : PFMAP);
+    REG_BG_OFS_SUB[0].x = REG_BG_OFS_SUB[0].y = 0;
+    tonccpy(pal_bg_mem_sub+0x00, palsrc, sizeof(gray4pal));
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #endif
   }
 }
 
@@ -237,10 +262,18 @@ static const BarsListEntry plugerects[] = {
 
 void draw_barslist(const BarsListEntry *rects) {
   canvasInit(&screen, 0);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  canvasInit(&screen_sub, 0);
+  #endif
   for(; rects->l < SCREEN_WIDTH; ++rects) {
     canvasRectfill(&screen,
                    rects->l, rects->t, rects->r, rects->b,
                    rects->color);
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    canvasRectfill(&screen_sub,
+                   rects->l, rects->t, rects->r, rects->b,
+                   rects->color);
+    #endif
   }
 }
 
@@ -298,6 +331,12 @@ static void do_bars(const BarsListEntry *rects, helpdoc_kind helpsect) {
     REG_BG_OFS[0].x = REG_BG_OFS[0].y = 0;
     tonccpy(pal_bg_mem+0x00, smptePalettes[bright], sizeof(smptePalettes[0]));
     REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
+    REG_BG_OFS_SUB[0].x = REG_BG_OFS_SUB[0].y = 0;
+    tonccpy(pal_bg_mem_sub+0x00, smptePalettes[bright], sizeof(smptePalettes[0]));
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #endif
     #ifdef __NDS__
     if(beep != last_beep) {
       if(beep)
@@ -332,9 +371,16 @@ void activity_pluge(void) {
     if (x == 8) x = ((SCREEN_WIDTH >> 3) - 8);
     unsigned int stride = screen.height * 8;
     uint32_t *tile = screen.chrBase + stride * x + 8;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    uint32_t *tile_sub = screen_sub.chrBase + stride * x + 8;
+    #endif
     for (unsigned int yleft = ((SCREEN_HEIGHT - 16) / 2); yleft > 0; --yleft) {
       *tile++ = 0x23232323;
       *tile++ = 0x32323232;
+      #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+      *tile_sub++ = 0x23232323;
+      *tile_sub++ = 0x32323232;
+      #endif
     }
   }
   
@@ -344,6 +390,14 @@ void activity_pluge(void) {
       se_mat[PFOVERLAY][y][x] = ((SCREEN_HEIGHT >> 3) * 32) + ((y & 0x03) << 2) + ((x + (((SCREEN_WIDTH % 32) >> 3) / 2)) & 0x03);
     }
   }
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  LZ77UnCompVram(pluge_shark_6color_chrTiles, tile_mem_sub[0][(SCREEN_HEIGHT >> 3) * 32].data);
+  for (unsigned int y = 0; y < (SCREEN_HEIGHT >> 3); ++y) {
+    for (unsigned int x = 0; x < (SCREEN_WIDTH >> 3); ++x) {
+      se_mat_sub[PFOVERLAY][y][x] = ((SCREEN_HEIGHT >> 3) * 32) + ((y & 0x03) << 2) + ((x + (((SCREEN_WIDTH % 32) >> 3) / 2)) & 0x03);
+    }
+  }
+  #endif
 
   while (1) {
     read_pad_help_check(helpsect_pluge);
@@ -370,6 +424,18 @@ void activity_pluge(void) {
               sizeof(plugePaletteNTSC));
     }
     REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(shark ? PFOVERLAY : PFMAP);
+    REG_BG_OFS_SUB[0].y = REG_BG_OFS_SUB[0].x = 0;
+    if (shark) {
+      tonccpy(pal_bg_mem_sub+0x00, pluge_shark_palettes[bright],
+              sizeof(pluge_shark_6color_chrPal));
+    } else {
+      tonccpy(pal_bg_mem_sub+0x00, bright ? plugePaletteNTSCJ : plugePaletteNTSC,
+              sizeof(plugePaletteNTSC));
+    }
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #endif
   }
 }
 
@@ -457,7 +523,7 @@ static void draw_gcbars(const TileCanvas* graiety) {
 }
 
 void activity_gcbars(void) {
-  unsigned int REG_BGCNT0 = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
+  unsigned int bgctrl0 = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
 
   load_common_bg_tiles();
   // Draw 5-pixel-wide vertical bars
@@ -465,6 +531,12 @@ void activity_gcbars(void) {
     8, 1, NUM_PIXELS_PER_GCBAR_PIECE, 1, tile_mem[0][0x40 - NUM_PIXELS_PER_GCBAR_PIECE].data, PFMAP, 0, 0x40 - NUM_PIXELS_PER_GCBAR_PIECE, se_mat
   };
   draw_gcbars(&graiety);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  static const TileCanvas graiety_sub = {
+    8, 1, NUM_PIXELS_PER_GCBAR_PIECE, 1, tile_mem_sub[0][0x40 - NUM_PIXELS_PER_GCBAR_PIECE].data, PFMAP, 0, 0x40 - NUM_PIXELS_PER_GCBAR_PIECE, se_mat_sub
+  };
+  draw_gcbars(&graiety_sub);
+  #endif
   
   // Draw labels on primary map
   vwfDrawLabelsPositionBased(gcbars_labels, gcbars_positions, PFMAP, 0x40);
@@ -475,15 +547,10 @@ void activity_gcbars(void) {
       return;
     }
     if (new_keys & KEY_A) {
-      REG_BGCNT0 ^= BG_SBB(PFMAP) ^ BG_SBB(PFOVERLAY);
+      bgctrl0 ^= BG_SBB(PFMAP) ^ BG_SBB(PFOVERLAY);
     }
 
     VBlankIntrWait();
-    REG_BGCNT[0] = REG_BGCNT0;
-    REG_BG_OFS[0].x = REG_BG_OFS[0].y = 0;
-    pal_bg_mem[0] = RGB5(0, 0, 0);
-    pal_bg_mem[1] = RGB5(31, 31, 31);
-
     // Calculate the color gradient
     unsigned int c = 0;
     const unsigned short *palramp = gcbars_palramps;
@@ -496,9 +563,24 @@ void activity_gcbars(void) {
         }
       }
       pal_bg_mem[p] = c;
+      #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+      pal_bg_mem_sub[p] = c;
+      #endif
       c += *palramp;
     }
+
+    REG_BGCNT[0] = bgctrl0;
+    REG_BG_OFS[0].x = REG_BG_OFS[0].y = 0;
+    pal_bg_mem[0] = RGB5(0, 0, 0);
+    pal_bg_mem[1] = RGB5(31, 31, 31);
     REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_BGCNT_SUB[0] = bgctrl0;
+    REG_BG_OFS_SUB[0].x = REG_BG_OFS_SUB[0].y = 0;
+    pal_bg_mem_sub[0] = RGB5(0, 0, 0);
+    pal_bg_mem_sub[1] = RGB5(31, 31, 31);
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #endif
   }
 }
 
@@ -536,6 +618,12 @@ void activity_gray_ramp(void) {
     0, 1, GRAY_RAMP_TILES, 1, tile_mem[0][0].data, PFMAP, 0, 0, se_mat
   };
   draw_gray_ramp(&graiety);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  static const TileCanvas graiety_sub = {
+    0, 1, GRAY_RAMP_TILES, 1, tile_mem_sub[0][0].data, PFMAP, 0, 0, se_mat_sub
+  };
+  draw_gray_ramp(&graiety_sub);
+  #endif
   
   // TODO: Make the tilemap with palette for the custom canvas
   while (1) {
@@ -545,17 +633,25 @@ void activity_gray_ramp(void) {
       return;
     }
 
-    VBlankIntrWait();
-    REG_BGCNT[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
-    REG_BG_OFS[0].x = REG_BG_OFS[0].y = 0;
-    
+    VBlankIntrWait();    
     unsigned int c = 0;
     for (unsigned int p = 1; p < 64; ++p) {
       pal_bg_mem[p] = c;
+      #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+      pal_bg_mem_sub[p] = c;
+      #endif
       c += RGB5(1, 1, 1);
       if ((p & 0x0F) == 8) p += 8;
     }
+
+    REG_BGCNT[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
+    REG_BG_OFS[0].x = REG_BG_OFS[0].y = 0;
     REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
+    REG_BG_OFS_SUB[0].x = REG_BG_OFS_SUB[0].y = 0;
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    #endif
   }
 }
 
@@ -578,6 +674,7 @@ static const unsigned short full_stripes_colors[10][2] = {
   { RGB5(31, 0, 0), RGB5( 0, 0,31) }
 };
 
+#define FULL_STRIPES_Y_OFFSET ((((SCREEN_HEIGHT >> 3) - 4) % 5) ? 4 : 8)
 
 static void do_full_stripes(helpdoc_kind helpsect) {
   unsigned int pattern = 0, inverted = 0, frame = 0;
@@ -589,6 +686,14 @@ static void do_full_stripes(helpdoc_kind helpsect) {
   // row 19: frame counter
   dma_memset16(se_mat[PFOVERLAY], 0x0000, 32*(SCREEN_HEIGHT >> 3)*2);
   loadMapRowMajor(&(se_mat[PFOVERLAY][(SCREEN_HEIGHT >> 3) - 1][(SCREEN_WIDTH >> 3) - 6]), 0x6002, 6, 1);
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  // tile 0: blank
+  dma_memset16(tile_mem_sub[0][0].data, 0x0000, 32);
+
+  // row 19: frame counter
+  dma_memset16(se_mat_sub[PFOVERLAY], 0x0000, 32*(SCREEN_HEIGHT >> 3)*2);
+  loadMapRowMajor(&(se_mat_sub[PFOVERLAY][(SCREEN_HEIGHT >> 3) - 1][(SCREEN_WIDTH >> 3) - 6]), 0x6002, 6, 1);
+  #endif
 
   while (1) {
     read_pad_help_check(helpsect);
@@ -614,10 +719,7 @@ static void do_full_stripes(helpdoc_kind helpsect) {
     REG_BGCNT[1] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
     REG_BGCNT[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFOVERLAY);
     REG_BG_OFS[0].x = REG_BG_OFS[0].y = REG_BG_OFS[1].x = 0;
-    if(((SCREEN_HEIGHT >> 3) - 4) % 5)
-        REG_BG_OFS[1].y = 4;
-    else
-        REG_BG_OFS[1].y = 8;
+    REG_BG_OFS[1].y = FULL_STRIPES_Y_OFFSET;
     pal_bg_mem[0] = RGB5(0, 0, 0);
     for (int c = 0; c < 10; ++c) {
       pal_bg_mem[c * 16 + 1] = full_stripes_colors[c][0];
@@ -635,12 +737,38 @@ static void do_full_stripes(helpdoc_kind helpsect) {
     // Draw the frame counter
     dma_memset16(tile_mem[0][2].data, 0x2222, 32*6);
     vwf8Puts(tile_mem[0][2].data, help_line_buffer, 4, 1);
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_BGCNT_SUB[1] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFOVERLAY);
+    REG_BG_OFS_SUB[0].x = REG_BG_OFS_SUB[0].y = REG_BG_OFS_SUB[1].x = 0;
+    REG_BG_OFS_SUB[1].y = FULL_STRIPES_Y_OFFSET;
+    pal_bg_mem_sub[0] = RGB5(0, 0, 0);
+    for (int c = 0; c < 10; ++c) {
+      pal_bg_mem_sub[c * 16 + 1] = full_stripes_colors[c][0];
+      pal_bg_mem_sub[c * 16 + 2] = full_stripes_colors[c][1];
+    }
+    REG_DISPCNT_SUB = lcdcvalue;
+
+    // Draw the pattern
+    dst = tile_mem_sub[0][1].data;
+    for (unsigned int i = 4; i > 0; --i) {
+      *dst++ = full_stripes_patterns[pattern][0] ^ inverted;
+      *dst++ = full_stripes_patterns[pattern][1] ^ inverted;
+    }
+
+    // Draw the frame counter
+    dma_memset16(tile_mem_sub[0][2].data, 0x2222, 32*6);
+    vwf8Puts(tile_mem_sub[0][2].data, help_line_buffer, 4, 1);
+    #endif
   }
 }
 
 void activity_full_stripes(void) {
   // Clear the screen
   dma_memset16(se_mat[PFMAP], 0x6001, 32*((SCREEN_HEIGHT >> 3) + 1)*2);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  dma_memset16(se_mat_sub[PFMAP], 0x6001, 32*((SCREEN_HEIGHT >> 3) + 1)*2);
+  #endif
   do_full_stripes(helpsect_full_screen_stripes);
 }
 
@@ -661,6 +789,10 @@ void activity_color_bleed(void) {
   // Clear the screen
   dma_memset16(se_mat[PFMAP], 0x0000, 32*((SCREEN_HEIGHT >> 3) + 1)*2);
   draw_stripe_regions(se_mat);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  dma_memset16(se_mat_sub[PFMAP], 0x0000, 32*((SCREEN_HEIGHT >> 3) + 1)*2);
+  draw_stripe_regions(se_mat_sub);
+  #endif
   do_full_stripes(helpsect_color_bleed);
 }
 
@@ -700,6 +832,14 @@ void activity_solid_color(void) {
 
   // Allocate canvas for the RGB editing box
   loadMapRowMajor(&(se_mat[PFMAP][1][26]), 0x0001, 3, 3);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  // Clear the screen
+  dma_memset16(se_mat_sub[PFMAP], 0x0000, 32*(SCREEN_HEIGHT >> 3)*2);
+  dma_memset16(tile_mem_sub[0][0].data, 0x0000, 32);
+
+  // Allocate canvas for the RGB editing box
+  loadMapRowMajor(&(se_mat_sub[PFMAP][1][26]), 0x0001, 3, 3);
+  #endif
 
   while (1) {
     read_pad_help_check(helpsect_solid_color_screen);
@@ -724,6 +864,9 @@ void activity_solid_color(void) {
         ++rgb_vals[y];
       }
       solid_color_draw_edit_box(rgb_vals, y, &tile_mem[0][0]);
+      #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+      solid_color_draw_edit_box(rgb_vals, y, &tile_mem_sub[0][0]);
+      #endif
     } else {
       if (new_keys & KEY_RIGHT) {
         x += 1;
@@ -741,6 +884,34 @@ void activity_solid_color(void) {
     pal_bg_mem[1] = RGB5(31, 31, 31);
     pal_bg_mem[2] = RGB5(0, 0, 0);
     REG_DISPCNT = showeditbox ? (DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW) : ACTIVATE_SCREEN_HW;
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
+    REG_BG_OFS_SUB[0].x = REG_BG_OFS_SUB[0].y = 0;
+    pal_bg_mem_sub[0] = x < 4 ? solid_colors[x] : RGB5(rgb_vals[0], rgb_vals[1], rgb_vals[2]);
+    pal_bg_mem_sub[1] = RGB5(31, 31, 31);
+    pal_bg_mem_sub[2] = RGB5(0, 0, 0);
+    REG_DISPCNT_SUB = showeditbox ? (DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW) : ACTIVATE_SCREEN_HW;
+    #endif
+  }
+}
+
+static void set_palette_convergence(u16* chosen_pal_bg_mem, u8 cur_side, u8 gridinvert, u8 griddepth, u8 colors_border) {
+  if (cur_side != 0) {
+    chosen_pal_bg_mem[0x03] = RGB5(31,31,31);
+    chosen_pal_bg_mem[0x13] = RGB5( 0, 0,31);
+    chosen_pal_bg_mem[0x23] = RGB5( 0,31, 0);
+    chosen_pal_bg_mem[0x33] = RGB5(31, 0, 0);
+    chosen_pal_bg_mem[0x02] = colors_border ? 0 : RGB5(31,31,31);
+    chosen_pal_bg_mem[0x12] = colors_border ? 0 : RGB5( 0, 0,31);
+    chosen_pal_bg_mem[0x22] = colors_border ? 0 : RGB5( 0,31, 0);
+    chosen_pal_bg_mem[0x32] = colors_border ? 0 : RGB5(31, 0, 0);
+  } else {
+    // Set palette for grid
+    unsigned int color = gridinvert ? 0x7FFF : 0;
+    for (unsigned int i = 0; i < 4; ++i) {
+      chosen_pal_bg_mem[i] = color;
+      if (i == griddepth) color = color ^ 0x7FFF;
+    }
   }
 }
 
@@ -759,6 +930,17 @@ void activity_convergence(void) {
       se_mat[PFOVERLAY][y][x] = tile;
     }
   }
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  bitunpack2(tile_mem_sub[0][0].data, convergence_chrTiles, sizeof(convergence_chrTiles));
+  dma_memset16(se_mat_sub[PFMAP], 0x04, 32*(SCREEN_HEIGHT >> 3)*2); 
+  for (unsigned int y = 0; y < (SCREEN_HEIGHT >> 3); ++y) {
+    unsigned int rowtilebase = (((y & 3) == 3) << 1) | ((y & 4) ? 0x2000 : 0);
+    for (unsigned int x = 0; x < (SCREEN_WIDTH >> 3); ++x) {
+      unsigned int tile = ((x & 3) == 3) | ((x & 4) ? 0x1000 : 0) | rowtilebase;
+      se_mat_sub[PFOVERLAY][y][x] = tile;
+    }
+  }
+  #endif
 
   while (1) {
     read_pad_help_check(helpsect_convergence);
@@ -782,23 +964,14 @@ void activity_convergence(void) {
                  |BG_SBB(PFMAP-cur_side));
     REG_BG_OFS[0].x = REG_BG_OFS[0].y = 0;
     REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
-    if (cur_side != 0) {
-      pal_bg_mem[0x03] = RGB5(31,31,31);
-      pal_bg_mem[0x13] = RGB5( 0, 0,31);
-      pal_bg_mem[0x23] = RGB5( 0,31, 0);
-      pal_bg_mem[0x33] = RGB5(31, 0, 0);
-      pal_bg_mem[0x02] = colors_border ? 0 : RGB5(31,31,31);
-      pal_bg_mem[0x12] = colors_border ? 0 : RGB5( 0, 0,31);
-      pal_bg_mem[0x22] = colors_border ? 0 : RGB5( 0,31, 0);
-      pal_bg_mem[0x32] = colors_border ? 0 : RGB5(31, 0, 0);
-    } else {
-      // Set palette for grid
-      unsigned int color = gridinvert ? 0x7FFF : 0;
-      for (unsigned int i = 0; i < 4; ++i) {
-        pal_bg_mem[i] = color;
-        if (i == griddepth) color = color ^ 0x7FFF;
-      }
-    }
+    set_palette_convergence(pal_bg_mem, cur_side, gridinvert, griddepth, colors_border);
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_BGCNT_SUB[0] = (BG_4BPP|BG_SIZE0|BG_CBB(0)
+                 |BG_SBB(PFMAP-cur_side));
+    REG_BG_OFS_SUB[0].x = REG_BG_OFS_SUB[0].y = 0;
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | ACTIVATE_SCREEN_HW;
+    set_palette_convergence(pal_bg_mem_sub, cur_side, gridinvert, griddepth, colors_border);
+    #endif
   }
 
 }
diff --git a/gba/src/stopwatch.c b/gba/src/stopwatch.c
index b0a3815..a946770 100644
--- a/gba/src/stopwatch.c
+++ b/gba/src/stopwatch.c
@@ -104,7 +104,7 @@ static void draw_stopwatch_hand(unsigned int phase) {
 
 void activity_stopwatch() {
   unsigned char digits[NUM_DIGITS] = {0};
-  unsigned int running = 0, is_lap = 0, hide_face = 0, show_ruler = 0, face_phase = 0;
+  unsigned int running = 0, is_lap = 0, hide_face = 0, show_ruler = 0, face_phase = 0, printed_frames = 0;
 
   dma_memset16(se_mat[PFMAP], 0x0000, 32*(SCREEN_HEIGHT >> 3)*2);
   dma_memset16(se_mat[TIMEMAP], 0x0000, 32*(SCREEN_HEIGHT >> 3)*2);
@@ -112,19 +112,39 @@ void activity_stopwatch() {
   bitunpack2(tile_mem[0][64].data, stopwatchdigits_chrTiles, sizeof(stopwatchdigits_chrTiles));
   bitunpack2(tile_mem_obj[0][0].data, stopwatchhand_chrTiles, sizeof(stopwatchhand_chrTiles));
   load_flat_map(&(se_mat[PFMAP][6][(SCREEN_WIDTH>>4)-6]), stopwatchface_chrMap, 12, 13);
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  dma_memset16(se_mat_sub[PFMAP], 0x0000, 32*(SCREEN_HEIGHT >> 3)*2);
+  dma_memset16(se_mat_sub[TIMEMAP], 0x0000, 32*(SCREEN_HEIGHT >> 3)*2);
+  bitunpack1(tile_mem_sub[0][0].data, stopwatchface_chrTiles, sizeof(stopwatchface_chrTiles));
+  bitunpack2(tile_mem_sub[0][64].data, stopwatchdigits_chrTiles, sizeof(stopwatchdigits_chrTiles));
+  bitunpack2(tile_mem_obj_sub[0][0].data, stopwatchhand_chrTiles, sizeof(stopwatchhand_chrTiles));
+  load_flat_map(&(se_mat_sub[PFMAP][6][(SCREEN_WIDTH>>4)-6]), stopwatchface_chrMap, 12, 13);
+  #endif
 
   vwfDrawLabelsPositionBased(sw_labels, sw_positions, TIMEMAP, 0x4080);
-  
+
   // Draw colons
   for (int i = 2; i < 8; i += 2) {
     unsigned int x = sw_digitx[i] + 2;
     se_mat[TIMEMAP][4][x] = se_mat[TIMEMAP][3][x] = 0x107C;
   };
-  
+
   // Draw ruler
   for (int i = 0; i < (SCREEN_HEIGHT >> 3); ++i) {
     se_mat[PFMAP][i][1 + (i & 0x01)] = 0x7D;
   }
+  #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+  // Draw colons
+  for (int i = 2; i < 8; i += 2) {
+    unsigned int x = sw_digitx[i] + 2;
+    se_mat_sub[TIMEMAP][4][x] = se_mat_sub[TIMEMAP][3][x] = 0x107C;
+  };
+
+  // Draw ruler
+  for (int i = 0; i < (SCREEN_HEIGHT >> 3); ++i) {
+    se_mat_sub[PFMAP][i][1 + (i & 0x01)] = 0x7D;
+  }
+  #endif
 
   do {
     read_pad_help_check(helpsect_stopwatch);
@@ -162,12 +182,21 @@ void activity_stopwatch() {
       }
     }
 
-    if (!is_lap) face_phase = digits[0];
+    if (!is_lap) {
+      face_phase = digits[0];
+      printed_frames = digits[0] + (digits[1] * 10);
+    }
+
     oam_used = 0;
     draw_stopwatch_hand(face_phase);
     ppu_clear_oam(oam_used);
 
     VBlankIntrWait();
+    #ifdef __NDS__
+    bool final_show_ruler = (show_ruler & (1 << ((printed_frames >> 1) & 1)));
+    #else
+    bool final_show_ruler = (show_ruler & (1 << (printed_frames & 1)));
+    #endif
     REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | DCNT_BG1 | DCNT_OBJ_1D | DCNT_OBJ | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
     REG_BGCNT[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
     REG_BGCNT[1] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(TIMEMAP);
@@ -175,13 +204,27 @@ void activity_stopwatch() {
     REG_BG_OFS[1].x = DIGITS_OFFSET_X;
     pal_bg_mem[0] = RGB5(31, 31, 31);
     pal_bg_mem[1] = hide_face ? RGB5(31, 31, 31) : RGB5(23, 23, 23);
-    bool final_show_ruler = (show_ruler & (1 << (face_phase & 1)));
     pal_bg_mem[3] = final_show_ruler ? RGB5(23, 0, 0) : RGB5(31, 31, 31);
     pal_bg_mem[65] = RGB5(0, 0, 0);
     tonccpy(pal_bg_mem+0x10, invgray4pal, sizeof(invgray4pal));
     tonccpy(pal_bg_mem+0x21, bluepalette, sizeof(bluepalette));
     tonccpy(pal_bg_mem+0x31, redpalette, sizeof(redpalette));
     tonccpy(pal_obj_mem+0x00, invgray4pal, sizeof(invgray4pal));
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    REG_DISPCNT_SUB = DCNT_MODE0 | DCNT_BG0 | DCNT_BG1 | DCNT_OBJ_1D | DCNT_OBJ | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
+    REG_BGCNT_SUB[0] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(PFMAP);
+    REG_BGCNT_SUB[1] = BG_4BPP|BG_SIZE0|BG_CBB(0)|BG_SBB(TIMEMAP);
+    REG_BG_OFS_SUB[0].x = REG_BG_OFS_SUB[0].y = REG_BG_OFS_SUB[1].y = 0;
+    REG_BG_OFS_SUB[1].x = DIGITS_OFFSET_X;
+    pal_bg_mem_sub[0] = RGB5(31, 31, 31);
+    pal_bg_mem_sub[1] = hide_face ? RGB5(31, 31, 31) : RGB5(23, 23, 23);
+    pal_bg_mem_sub[3] = final_show_ruler ? RGB5(23, 0, 0) : RGB5(31, 31, 31);
+    pal_bg_mem_sub[65] = RGB5(0, 0, 0);
+    tonccpy(pal_bg_mem_sub+0x10, invgray4pal, sizeof(invgray4pal));
+    tonccpy(pal_bg_mem_sub+0x21, bluepalette, sizeof(bluepalette));
+    tonccpy(pal_bg_mem_sub+0x31, redpalette, sizeof(redpalette));
+    tonccpy(pal_obj_mem_sub+0x00, invgray4pal, sizeof(invgray4pal));
+    #endif
     ppu_copy_oam();
 
     // Update digits
@@ -195,14 +238,26 @@ void activity_stopwatch() {
           tilenum += (digits[0] & 1) ? 0x3000 : 0x2000;  // colored digits
         }
         for (unsigned int row = 2; row < 5; ++row) {
-          se_mat[TIMEMAP][row][x] = tilenum++;
-          se_mat[TIMEMAP][row][x + 1] = tilenum++;
+          se_mat[TIMEMAP][row][x] = tilenum;
+          se_mat[TIMEMAP][row][x + 1] = tilenum + 1;
+          #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+          se_mat_sub[TIMEMAP][row][x] = tilenum;
+          se_mat_sub[TIMEMAP][row][x + 1] = tilenum + 1;
+          #endif
+          tilenum += 2;
         }
       }
       se_mat[TIMEMAP][5][START_TILE_SW_X+16] = se_mat[TIMEMAP][5][START_TILE_SW_X+17] = 0;
+      #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+      se_mat_sub[TIMEMAP][5][START_TILE_SW_X+16] = se_mat_sub[TIMEMAP][5][START_TILE_SW_X+17] = 0;
+      #endif
     } else {
       se_mat[TIMEMAP][5][START_TILE_SW_X+16] = 0x107E;  // LA
       se_mat[TIMEMAP][5][START_TILE_SW_X+17] = 0x107F;  // P
+      #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+      se_mat_sub[TIMEMAP][5][START_TILE_SW_X+16] = 0x107E;  // LA
+      se_mat_sub[TIMEMAP][5][START_TILE_SW_X+17] = 0x107F;  // P
+      #endif
     }
   } while (!(new_keys & KEY_B));
 }
diff --git a/gba/src/vwflabels.c b/gba/src/vwflabels.c
index eb551b9..0b3c332 100644
--- a/gba/src/vwflabels.c
+++ b/gba/src/vwflabels.c
@@ -50,6 +50,14 @@ void vwfDrawLabelsPositionBased(const char *labels, const char *positions, unsig
     
     // Fill the nametable
     loadMapRowMajor(&(se_mat[sbb][y >> 3][x >> 3]), tilenum & 0xF3FF, txtw, 1);
+    #if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
+    chrdst = tile_mem_sub[0][tilenum & 0x07FF].data;
+    dma_memset16(chrdst, 0x0000, 32 * txtw);
+    strend = vwf8Puts(chrdst, labels, x & 0x07, 1);
+    
+    // Fill the nametable
+    loadMapRowMajor(&(se_mat_sub[sbb][y >> 3][x >> 3]), tilenum & 0xF3FF, txtw, 1);
+    #endif
     tilenum += txtw;
 
     if (*strend == 0) break;