DS(i): Add custom color LUT support

This commit is contained in:
RocketRobz 2024-02-26 18:51:32 -07:00
parent 55d276c75e
commit 3e01affd73
7 changed files with 143 additions and 15 deletions

View File

@ -0,0 +1,6 @@
#ifndef GET_FILE_SIZE
#define GET_FILE_SIZE
off_t getFileSize(const char *fileName);
#endif // GET_FILE_SIZE

View File

@ -68,6 +68,10 @@ extern int bg2Main;
extern int bg3Main; extern int bg3Main;
extern int bg3Sub; extern int bg3Sub;
extern u16* colorTable;
extern void applyColorLut(u16 *palette, int size);
extern void copyPalette(u16 *dst, const u16 *src, int size);
extern bool showCursor; extern bool showCursor;
extern int cursorAlpha; extern int cursorAlpha;
@ -156,6 +160,7 @@ void GFX::loadSheets() {
for(unsigned i=0;i<image.size()/4;i++) { for(unsigned i=0;i<image.size()/4;i++) {
charSpriteMem[i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15); charSpriteMem[i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
} }
applyColorLut(charSpriteMem, image.size()/4);
image.clear(); image.clear();
lodepng::decode(image, width, height, sysRegion==CFG_REGION_JPN ? "nitro:/graphics/gui/titleJ.png" : "nitro:/graphics/gui/title.png"); lodepng::decode(image, width, height, sysRegion==CFG_REGION_JPN ? "nitro:/graphics/gui/titleJ.png" : "nitro:/graphics/gui/title.png");
bool alternatePixel = false; bool alternatePixel = false;
@ -184,6 +189,9 @@ void GFX::loadSheets() {
} }
} }
bmpImageBuffer[1][i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15); bmpImageBuffer[1][i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
if (colorTable) {
bmpImageBuffer[1][i] = colorTable[bmpImageBuffer[1][i]];
}
if (charSpriteAlpha[i] == 255) { if (charSpriteAlpha[i] == 255) {
bmpImageBuffer[0][i] = bmpImageBuffer[1][i]; bmpImageBuffer[0][i] = bmpImageBuffer[1][i];
} else if (charSpriteAlpha[i] == 0) { } else if (charSpriteAlpha[i] == 0) {
@ -214,6 +222,9 @@ void GFX::loadSheets() {
} }
} }
bmpImageBuffer2[1][i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15); bmpImageBuffer2[1][i] = image[i*4]>>3 | (image[(i*4)+1]>>3)<<5 | (image[(i*4)+2]>>3)<<10 | BIT(15);
if (colorTable) {
bmpImageBuffer2[1][i] = colorTable[bmpImageBuffer2[1][i]];
}
if (charSpriteAlpha[i] == 255) { if (charSpriteAlpha[i] == 255) {
bmpImageBuffer2[0][i] = bmpImageBuffer2[1][i]; bmpImageBuffer2[0][i] = bmpImageBuffer2[1][i];
} else if (charSpriteAlpha[i] == 0) { } else if (charSpriteAlpha[i] == 0) {
@ -270,7 +281,7 @@ void updateTitleScreen(const int metalXposBase) {
for (int i = 0; i < 256*192; i+=2) { for (int i = 0; i < 256*192; i+=2) {
bgGetGfxPtr(bg3Sub)[i/2] += 0x1010; // Shift pallete 16 colors further bgGetGfxPtr(bg3Sub)[i/2] += 0x1010; // Shift pallete 16 colors further
} }
tonccpy(BG_PALETTE_SUB + 0x10, photo_bgPal, 240*sizeof(u16)); copyPalette(BG_PALETTE_SUB + 0x10, photo_bgPal, 240);
titleBottomLoaded = true; titleBottomLoaded = true;
} }
} }
@ -298,9 +309,14 @@ void GFX::loadBgSprite(void) {
if (dsiFeatures()) { if (dsiFeatures()) {
swiWaitForVBlank(); // Prevent screen tearing swiWaitForVBlank(); // Prevent screen tearing
if (colorTable) {
dmaFillHalfWords(colorTable[0xFFFF], bgGetGfxPtr(bg2Main), 0x18000);
dmaFillHalfWords(colorTable[0xFFFF], bgGetGfxPtr(bg3Main), 0x18000);
} else {
dmaFillHalfWords(0xFFFF, bgGetGfxPtr(bg2Main), 0x18000); dmaFillHalfWords(0xFFFF, bgGetGfxPtr(bg2Main), 0x18000);
dmaFillHalfWords(0xFFFF, bgGetGfxPtr(bg3Main), 0x18000); dmaFillHalfWords(0xFFFF, bgGetGfxPtr(bg3Main), 0x18000);
} }
}
timeOutside = 2; // Default is Nighttime timeOutside = 2; // Default is Nighttime
int aniFrames = 0; int aniFrames = 0;
@ -671,6 +687,10 @@ void GFX::loadBgSprite(void) {
if ((i % 256) == 255) alternatePixel = !alternatePixel; if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel; alternatePixel = !alternatePixel;
} }
applyColorLut(bgSpriteMem, image.size()/4);
if (dsiFeatures()) {
applyColorLut(bgSpriteMem2, image.size()/4);
}
bgSpriteLoaded = true; bgSpriteLoaded = true;
bgAnimationFrame = 0; bgAnimationFrame = 0;
@ -748,6 +768,10 @@ void GFX::loadBgSprite(void) {
if ((p % 256) == 255) alternatePixel = !alternatePixel; if ((p % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel; alternatePixel = !alternatePixel;
} }
applyColorLut(bgSpriteMemExt[i-1], image.size()/4);
if (dsiFeatures()) {
applyColorLut(bgSpriteMemExt2[i-1], image.size()/4);
}
} }
if (studioBg == 64) { if (studioBg == 64) {
bgAnimationDelay = iFps/2; bgAnimationDelay = iFps/2;
@ -876,6 +900,10 @@ bool GFX::loadCharSprite(int num, const char* t3xPathPose, const char* t3xPathAl
if ((i % 256) == 255) alternatePixel = !alternatePixel; if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel; alternatePixel = !alternatePixel;
} }
applyColorLut(usePageFile ? charSpriteMem : charSpriteMem5, image.size()/4);
if (dsiFeatures()) {
applyColorLut(charSpriteMem5_2, image.size()/4);
}
if (usePageFile) { if (usePageFile) {
FILE* pageFile = fopen("fat:/_nds/pagefile.sys", "r+"); FILE* pageFile = fopen("fat:/_nds/pagefile.sys", "r+");
fseek(pageFile, ((0x18000*3)+(0xC000*3))*4, SEEK_SET); fseek(pageFile, ((0x18000*3)+(0xC000*3))*4, SEEK_SET);
@ -945,6 +973,10 @@ bool GFX::loadCharSprite(int num, const char* t3xPathPose, const char* t3xPathAl
if ((i % 256) == 255) alternatePixel = !alternatePixel; if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel; alternatePixel = !alternatePixel;
} }
applyColorLut(usePageFile ? charSpriteMem : charSpriteMem4, image.size()/4);
if (dsiFeatures()) {
applyColorLut(charSpriteMem4_2, image.size()/4);
}
if (usePageFile) { if (usePageFile) {
FILE* pageFile = fopen("fat:/_nds/pagefile.sys", "r+"); FILE* pageFile = fopen("fat:/_nds/pagefile.sys", "r+");
fseek(pageFile, ((0x18000*3)+(0xC000*3))*3, SEEK_SET); fseek(pageFile, ((0x18000*3)+(0xC000*3))*3, SEEK_SET);
@ -1014,6 +1046,10 @@ bool GFX::loadCharSprite(int num, const char* t3xPathPose, const char* t3xPathAl
if ((i % 256) == 255) alternatePixel = !alternatePixel; if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel; alternatePixel = !alternatePixel;
} }
applyColorLut(usePageFile ? charSpriteMem : charSpriteMem3, image.size()/4);
if (dsiFeatures()) {
applyColorLut(charSpriteMem3_2, image.size()/4);
}
if (usePageFile) { if (usePageFile) {
FILE* pageFile = fopen("fat:/_nds/pagefile.sys", "r+"); FILE* pageFile = fopen("fat:/_nds/pagefile.sys", "r+");
fseek(pageFile, ((0x18000*3)+(0xC000*3))*2, SEEK_SET); fseek(pageFile, ((0x18000*3)+(0xC000*3))*2, SEEK_SET);
@ -1097,6 +1133,10 @@ bool GFX::loadCharSprite(int num, const char* t3xPathPose, const char* t3xPathAl
if ((i % 256) == 255) alternatePixel = !alternatePixel; if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel; alternatePixel = !alternatePixel;
} }
applyColorLut(usePageFile ? charSpriteMem : charSpriteMem2, image.size()/4);
if (dsiFeatures()) {
applyColorLut(charSpriteMem2_2, image.size()/4);
}
if (usePageFile) { if (usePageFile) {
FILE* pageFile = fopen("fat:/_nds/pagefile.sys", "r+"); FILE* pageFile = fopen("fat:/_nds/pagefile.sys", "r+");
fseek(pageFile, (0x18000*3)+(0xC000*3), SEEK_SET); fseek(pageFile, (0x18000*3)+(0xC000*3), SEEK_SET);
@ -1158,6 +1198,10 @@ bool GFX::loadCharSprite(int num, const char* t3xPathPose, const char* t3xPathAl
if ((i % 256) == 255) alternatePixel = !alternatePixel; if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel; alternatePixel = !alternatePixel;
} }
applyColorLut(charSpriteMem, image.size()/4);
if (dsiFeatures()) {
applyColorLut(charSpriteMem_2, image.size()/4);
}
if (usePageFile && chracterSpriteFound[1]) { if (usePageFile && chracterSpriteFound[1]) {
FILE* pageFile = fopen("fat:/_nds/pagefile.sys", "r+"); FILE* pageFile = fopen("fat:/_nds/pagefile.sys", "r+");
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
@ -1258,6 +1302,10 @@ ITCM_CODE void GFX::loadCharSpriteMem(const int zoomIn, const bool* flipH) {
break; break;
} }
if (colorTable) {
fg = colorTable[fg];
}
int buffer = 0; int buffer = 0;
int x2 = 0; int x2 = 0;
u16 color = 0; u16 color = 0;

View File

@ -28,6 +28,7 @@
#include "screenCommon.hpp" #include "screenCommon.hpp"
#include "fontHandler.h" #include "fontHandler.h"
#include "myDSiMode.h" #include "myDSiMode.h"
#include "getFileSize.h"
#include "tonccpy.h" #include "tonccpy.h"
#include "arrow_back.h" #include "arrow_back.h"
@ -57,6 +58,8 @@ int bg3Sub;
u16* gfxSub; u16* gfxSub;
u16* colorTable = NULL;
// Ported from PAlib (obsolete) // Ported from PAlib (obsolete)
void SetBrightness(u8 screen, s8 bright) { void SetBrightness(u8 screen, s8 bright) {
u16 mode = 1 << 14; u16 mode = 1 << 14;
@ -87,6 +90,26 @@ void Gui__ChangeBrightness() {
SetBrightness(1, (fadecolor==255 ? fadealpha : -fadealpha)/8); SetBrightness(1, (fadecolor==255 ? fadealpha : -fadealpha)/8);
} }
void applyColorLut(u16 *palette, int size) {
if (!colorTable) {
return;
}
for (int i = 0; i < size; i++) {
palette[i] = colorTable[palette[i]];
}
}
// Copies a palette and applies color LUT if loaded
void copyPalette(u16 *dst, const u16 *src, int size) {
if (colorTable) {
for (int i = 0; i < size; i++) {
dst[i] = colorTable[src[i]];
}
return;
}
tonccpy(dst, src, size);
}
// Initialize GUI. // Initialize GUI.
void Gui::init(void) { void Gui::init(void) {
*(vu16*)0x0400006C |= BIT(14); *(vu16*)0x0400006C |= BIT(14);
@ -97,18 +120,36 @@ void Gui::init(void) {
videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE); videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE);
videoSetModeSub(MODE_5_2D | DISPLAY_BG3_ACTIVE); videoSetModeSub(MODE_5_2D | DISPLAY_BG3_ACTIVE);
// Set up enough texture memory for our textures
// Bank A is just 128kb and we are using 194 kb of
// sprites
vramSetBankA(VRAM_A_MAIN_BG); vramSetBankA(VRAM_A_MAIN_BG);
vramSetBankB(VRAM_B_MAIN_BG); vramSetBankB(VRAM_B_MAIN_BG);
vramSetBankC(VRAM_C_SUB_BG); vramSetBankC(VRAM_C_SUB_BG);
vramSetBankD(VRAM_D_SUB_SPRITE); vramSetBankD(VRAM_D_LCD);
vramSetBankE(VRAM_E_TEX_PALETTE);
vramSetBankF(VRAM_F_TEX_PALETTE_SLOT4);
vramSetBankG(VRAM_G_MAIN_SPRITE); vramSetBankG(VRAM_G_MAIN_SPRITE);
vramSetBankH(VRAM_H_SUB_BG_EXT_PALETTE); vramSetBankH(VRAM_H_SUB_BG_EXT_PALETTE);
vramSetBankI(VRAM_I_SUB_SPRITE_EXT_PALETTE); vramSetBankI(VRAM_I_SUB_SPRITE);
if (access("/_nds/colorLut/currentSetting.txt", F_OK) == 0) {
// Load color LUT
char lutName[128] = {0};
FILE* file = fopen("/_nds/colorLut/currentSetting.txt", "rb");
fread(lutName, 1, 128, file);
fclose(file);
char colorLutPath[256];
sprintf(colorLutPath, "/_nds/colorLut/%s.lut", lutName);
if (getFileSize(colorLutPath) == 0x20000) {
colorTable = new u16[0x20000/sizeof(u16)];
file = fopen(colorLutPath, "rb");
fread(colorTable, 1, 0x20000, file);
fclose(file);
tonccpy(VRAM_D, colorTable, 0x20000); // Copy LUT to VRAM
delete[] colorTable; // Free up RAM space
colorTable = VRAM_D;
}
}
bg3Main = bgInit(3, BgType_Bmp16, BgSize_B16_256x256, 0, 0); bg3Main = bgInit(3, BgType_Bmp16, BgSize_B16_256x256, 0, 0);
bgSetPriority(bg3Main, 0); bgSetPriority(bg3Main, 0);
@ -129,7 +170,7 @@ void Gui::init(void) {
// Load back button // Load back button
tonccpy(gfxSub, arrow_backTiles, arrow_backTilesLen); tonccpy(gfxSub, arrow_backTiles, arrow_backTilesLen);
tonccpy(SPRITE_PALETTE_SUB, arrow_backPal, arrow_backPalLen); copyPalette(SPRITE_PALETTE_SUB, arrow_backPal, arrow_backPalLen);
oamSet(&oamSub, oamSet(&oamSub,
0, 0,
@ -150,7 +191,7 @@ void Gui::init(void) {
gfxSub = oamAllocateGfx(&oamSub, SpriteSize_32x32, SpriteColorFormat_16Color); gfxSub = oamAllocateGfx(&oamSub, SpriteSize_32x32, SpriteColorFormat_16Color);
tonccpy(gfxSub, cursorTiles, cursorTilesLen); tonccpy(gfxSub, cursorTiles, cursorTilesLen);
tonccpy(SPRITE_PALETTE_SUB+16, cursorPal, cursorPalLen); copyPalette(SPRITE_PALETTE_SUB+16, cursorPal, cursorPalLen);
oamSet(&oamSub, oamSet(&oamSub,
1, 1,
@ -171,7 +212,7 @@ void Gui::init(void) {
gfxSub = oamAllocateGfx(&oamSub, SpriteSize_64x64, SpriteColorFormat_16Color); gfxSub = oamAllocateGfx(&oamSub, SpriteSize_64x64, SpriteColorFormat_16Color);
tonccpy(gfxSub, item_button0Tiles, item_button0TilesLen); tonccpy(gfxSub, item_button0Tiles, item_button0TilesLen);
tonccpy(SPRITE_PALETTE_SUB+32, item_button0Pal, item_button0PalLen); copyPalette(SPRITE_PALETTE_SUB+32, item_button0Pal, item_button0PalLen);
for (int i = 2; i <= 4; i++) { for (int i = 2; i <= 4; i++) {
oamSet(&oamSub, oamSet(&oamSub,
@ -236,7 +277,7 @@ void Gui::init(void) {
gfxSub = oamAllocateGfx(&oamSub, SpriteSize_64x64, SpriteColorFormat_16Color); gfxSub = oamAllocateGfx(&oamSub, SpriteSize_64x64, SpriteColorFormat_16Color);
tonccpy(gfxSub, icon_femaleTiles, icon_femaleTilesLen); tonccpy(gfxSub, icon_femaleTiles, icon_femaleTilesLen);
tonccpy(SPRITE_PALETTE_SUB+48, icon_femalePal, icon_femalePalLen); copyPalette(SPRITE_PALETTE_SUB+48, icon_femalePal, icon_femalePalLen);
for (int i = 14; i <= 16; i++) { for (int i = 14; i <= 16; i++) {
oamSet(&oamSub, oamSet(&oamSub,
@ -259,7 +300,7 @@ void Gui::init(void) {
gfxSub = oamAllocateGfx(&oamSub, SpriteSize_64x64, SpriteColorFormat_16Color); gfxSub = oamAllocateGfx(&oamSub, SpriteSize_64x64, SpriteColorFormat_16Color);
tonccpy(gfxSub, icon_maleTiles, icon_maleTilesLen); tonccpy(gfxSub, icon_maleTiles, icon_maleTilesLen);
tonccpy(SPRITE_PALETTE_SUB+64, icon_malePal, icon_malePalLen); copyPalette(SPRITE_PALETTE_SUB+64, icon_malePal, icon_malePalLen);
for (int i = 17; i <= 19; i++) { for (int i = 17; i <= 19; i++) {
oamSet(&oamSub, oamSet(&oamSub,

View File

@ -30,6 +30,7 @@ void ProductIdent::Logic(u32 hDown, u32 hHeld, touchPosition touch) {
u16* bgLoc = new u16[256*192]; u16* bgLoc = new u16[256*192];
extern int bg2Main; extern int bg2Main;
extern int bg3Main; extern int bg3Main;
extern void applyColorLut(u16 *palette, int size);
std::vector<unsigned char> image; std::vector<unsigned char> image;
unsigned width, height; unsigned width, height;
@ -44,6 +45,10 @@ void ProductIdent::Logic(u32 hDown, u32 hHeld, touchPosition touch) {
while (dmaBusy(0)); while (dmaBusy(0));
delete[] bgLoc; delete[] bgLoc;
} }
applyColorLut(bgGetGfxPtr(bg2Main), 0x18000/sizeof(u16));
if (dsiFeatures()) {
applyColorLut(bgGetGfxPtr(bg3Main), 0x18000/sizeof(u16));
}
graphicLoaded = true; graphicLoaded = true;
} }
} }

View File

@ -4,6 +4,8 @@
#include "tonccpy.h" #include "tonccpy.h"
#include "TextEntry.h" #include "TextEntry.h"
extern u16* colorTable;
FontGraphic smallFont; FontGraphic smallFont;
FontGraphic largeFont; FontGraphic largeFont;
@ -24,6 +26,11 @@ void fontInit() {
0xC631, 0xC631,
0xDEF7, 0xDEF7,
}; };
if (colorTable) {
for (int i = 1; i < 4; i++) {
palette[i] = colorTable[palette[i]];
}
}
tonccpy(BG_PALETTE, palette, sizeof(palette)); tonccpy(BG_PALETTE, palette, sizeof(palette));
tonccpy(BG_PALETTE_SUB, palette, sizeof(palette)); tonccpy(BG_PALETTE_SUB, palette, sizeof(palette));
} }

View File

@ -0,0 +1,16 @@
#include <nds.h>
#include <stdio.h>
off_t getFileSize(const char *fileName)
{
FILE* fp = fopen(fileName, "rb");
off_t fsize = 0;
if (fp) {
fseek(fp, 0, SEEK_END);
fsize = ftell(fp); // Get source file's size
fseek(fp, 0, SEEK_SET);
}
fclose(fp);
return fsize;
}

View File

@ -137,6 +137,7 @@ void RocketRobz::Logic(u32 hDown, u32 hHeld, touchPosition touch) {
if (!graphicLoaded) { if (!graphicLoaded) {
extern int bg2Main; extern int bg2Main;
extern int bg3Main; extern int bg3Main;
extern void applyColorLut(u16 *palette, int size);
std::vector<unsigned char> image; std::vector<unsigned char> image;
unsigned width, height; unsigned width, height;
@ -186,6 +187,10 @@ void RocketRobz::Logic(u32 hDown, u32 hHeld, touchPosition touch) {
if ((i % 256) == 255) alternatePixel = !alternatePixel; if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel; alternatePixel = !alternatePixel;
} }
applyColorLut(bgGetGfxPtr(bg2Main), 0x18000/sizeof(u16));
if (dsiFeatures()) {
applyColorLut(bgGetGfxPtr(bg3Main), 0x18000/sizeof(u16));
}
graphicLoaded = true; graphicLoaded = true;
} }
#endif #endif