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;