// SPDX-License-Identifier: CC0-1.0
//
// SPDX-FileContributor: Antonio Niño Díaz, 2024-2026

#include <nds.h>

// This example uses extended palettes for backgrounds. Each tile of the
// backgrounds is allowed to use one of the 16 256-color palettes, exactly like
// regular backgrounds are allowed to select one of the 16 16-color palettes for
// each tile.
//
// For this example, the ponypoke_0.png image is converted to use palette 12, and the
// forest_town.png image is converted to use palette 7. Check the ".grit" files for
// more details.
//
// Note that this example only uses regular backgrounds. It's also possible to
// use extended palettes with "extended affine" backgrounds in video modes 3-5,
// but not with "affine" or "bitmap" backgrounds.

// This is autogenerated from the files in the "graphics" folder
#include "ponypoke_0.h"
#include "forest_town.h"

int main(int argc, char *argv[])
{
    videoSetMode(MODE_0_2D);
    videoSetModeSub(MODE_0_2D);

    vramSetPrimaryBanks(VRAM_A_MAIN_BG, VRAM_B_LCD, VRAM_C_SUB_BG, VRAM_D_LCD);

    // Let the CPU access VRAM E and H to copy the extended palettes. Extended
    // palette VRAM can't be accessed by the CPU (background VRAM can be
    // accessed even without mapping it as LCD).
    vramSetBankE(VRAM_E_LCD);
    vramSetBankH(VRAM_H_LCD);

    // Enable extended palettes for backgrounds for both engines
    bgExtPaletteEnable();
    bgExtPaletteEnableSub();

    // Main engine backgrounds

    int bg0 = bgInitHidden(0, BgType_Text8bpp, BgSize_T_256x256, 0, 1);

    memcpy(bgGetGfxPtr(bg0), ponypoke_0Tiles, ponypoke_0TilesLen);
    memcpy(bgGetMapPtr(bg0), ponypoke_0Map, ponypoke_0MapLen);
    memcpy(&VRAM_E_EXT_PALETTE[0][12], ponypoke_0Pal, ponypoke_0PalLen);

    int bg1 = bgInitHidden(1, BgType_Text8bpp, BgSize_T_256x256, 4, 4);

    memcpy(bgGetGfxPtr(bg1), forest_townTiles, forest_townTilesLen);
    memcpy(bgGetMapPtr(bg1), forest_townMap, forest_townMapLen);
    memcpy(&VRAM_E_EXT_PALETTE[1][7], forest_townPal, forest_townPalLen);

    // Sub engine backgrounds (including the debug console)

    // https://mtheall.com/vram.html#SUB=1&T0=3&NT0=128&MB0=0&TB0=1&T1=1&NT1=512&MB1=2&TB1=2&S1=0&T2=1&NT2=512&MB2=4&TB2=5&S2=0

    consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 0, 1, false, true);

    int bg1sub = bgInitHiddenSub(1, BgType_Text8bpp, BgSize_T_256x256, 2, 2);

    memcpy(bgGetGfxPtr(bg1sub), ponypoke_0Tiles, ponypoke_0TilesLen);
    memcpy(bgGetMapPtr(bg1sub), ponypoke_0Map, ponypoke_0MapLen);
    memcpy(&VRAM_H_EXT_PALETTE[1][12], ponypoke_0Pal, ponypoke_0PalLen);

    int bg2sub = bgInitHiddenSub(2, BgType_Text8bpp, BgSize_T_256x256, 4, 5);

    memcpy(bgGetGfxPtr(bg2sub), forest_townTiles, forest_townTilesLen);
    memcpy(bgGetMapPtr(bg2sub), forest_townMap, forest_townMapLen);
    memcpy(&VRAM_H_EXT_PALETTE[2][7], forest_townPal, forest_townPalLen);

    // Setup VRAM as extended palette VRAM

    vramSetBankE(VRAM_E_BG_EXT_PALETTE);
    vramSetBankH(VRAM_H_SUB_BG_EXT_PALETTE);

    // Display backgrounds only when all of them are ready

    bgShow(bg0);
    bgShow(bg1);
    bgShow(bg1sub);
    bgShow(bg2sub);

    printf("PAD:   Scroll backgrounds\n");
    printf("START: Exit to loader\n");

    int x = 0, y = 0;

    while (1)
    {
        swiWaitForVBlank();

        bgUpdate();

        bgSetScroll(bg0, x, y);
        bgSetScroll(bg1sub, x, y);

        scanKeys();
        u16 keys_held = keysHeld();

        if (keys_held & KEY_UP)
            y++;
        else if (keys_held & KEY_DOWN)
            y--;

        if (keys_held & KEY_LEFT)
            x++;
        else if (keys_held & KEY_RIGHT)
            x--;

        if (keys_held & KEY_START)
            break;
    }

    return 0;
}
