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 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 int cursorAlpha;
@ -156,6 +160,7 @@ void GFX::loadSheets() {
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);
}
applyColorLut(charSpriteMem, image.size()/4);
image.clear();
lodepng::decode(image, width, height, sysRegion==CFG_REGION_JPN ? "nitro:/graphics/gui/titleJ.png" : "nitro:/graphics/gui/title.png");
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);
if (colorTable) {
bmpImageBuffer[1][i] = colorTable[bmpImageBuffer[1][i]];
}
if (charSpriteAlpha[i] == 255) {
bmpImageBuffer[0][i] = bmpImageBuffer[1][i];
} 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);
if (colorTable) {
bmpImageBuffer2[1][i] = colorTable[bmpImageBuffer2[1][i]];
}
if (charSpriteAlpha[i] == 255) {
bmpImageBuffer2[0][i] = bmpImageBuffer2[1][i];
} else if (charSpriteAlpha[i] == 0) {
@ -270,7 +281,7 @@ void updateTitleScreen(const int metalXposBase) {
for (int i = 0; i < 256*192; i+=2) {
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;
}
}
@ -298,9 +309,14 @@ void GFX::loadBgSprite(void) {
if (dsiFeatures()) {
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(bg3Main), 0x18000);
}
}
timeOutside = 2; // Default is Nighttime
int aniFrames = 0;
@ -671,6 +687,10 @@ void GFX::loadBgSprite(void) {
if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel;
}
applyColorLut(bgSpriteMem, image.size()/4);
if (dsiFeatures()) {
applyColorLut(bgSpriteMem2, image.size()/4);
}
bgSpriteLoaded = true;
bgAnimationFrame = 0;
@ -748,6 +768,10 @@ void GFX::loadBgSprite(void) {
if ((p % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel;
}
applyColorLut(bgSpriteMemExt[i-1], image.size()/4);
if (dsiFeatures()) {
applyColorLut(bgSpriteMemExt2[i-1], image.size()/4);
}
}
if (studioBg == 64) {
bgAnimationDelay = iFps/2;
@ -876,6 +900,10 @@ bool GFX::loadCharSprite(int num, const char* t3xPathPose, const char* t3xPathAl
if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel;
}
applyColorLut(usePageFile ? charSpriteMem : charSpriteMem5, image.size()/4);
if (dsiFeatures()) {
applyColorLut(charSpriteMem5_2, image.size()/4);
}
if (usePageFile) {
FILE* pageFile = fopen("fat:/_nds/pagefile.sys", "r+");
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;
alternatePixel = !alternatePixel;
}
applyColorLut(usePageFile ? charSpriteMem : charSpriteMem4, image.size()/4);
if (dsiFeatures()) {
applyColorLut(charSpriteMem4_2, image.size()/4);
}
if (usePageFile) {
FILE* pageFile = fopen("fat:/_nds/pagefile.sys", "r+");
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;
alternatePixel = !alternatePixel;
}
applyColorLut(usePageFile ? charSpriteMem : charSpriteMem3, image.size()/4);
if (dsiFeatures()) {
applyColorLut(charSpriteMem3_2, image.size()/4);
}
if (usePageFile) {
FILE* pageFile = fopen("fat:/_nds/pagefile.sys", "r+");
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;
alternatePixel = !alternatePixel;
}
applyColorLut(usePageFile ? charSpriteMem : charSpriteMem2, image.size()/4);
if (dsiFeatures()) {
applyColorLut(charSpriteMem2_2, image.size()/4);
}
if (usePageFile) {
FILE* pageFile = fopen("fat:/_nds/pagefile.sys", "r+");
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;
alternatePixel = !alternatePixel;
}
applyColorLut(charSpriteMem, image.size()/4);
if (dsiFeatures()) {
applyColorLut(charSpriteMem_2, image.size()/4);
}
if (usePageFile && chracterSpriteFound[1]) {
FILE* pageFile = fopen("fat:/_nds/pagefile.sys", "r+");
for (int i = 0; i < 3; i++) {
@ -1258,6 +1302,10 @@ ITCM_CODE void GFX::loadCharSpriteMem(const int zoomIn, const bool* flipH) {
break;
}
if (colorTable) {
fg = colorTable[fg];
}
int buffer = 0;
int x2 = 0;
u16 color = 0;

View File

@ -28,6 +28,7 @@
#include "screenCommon.hpp"
#include "fontHandler.h"
#include "myDSiMode.h"
#include "getFileSize.h"
#include "tonccpy.h"
#include "arrow_back.h"
@ -57,6 +58,8 @@ int bg3Sub;
u16* gfxSub;
u16* colorTable = NULL;
// Ported from PAlib (obsolete)
void SetBrightness(u8 screen, s8 bright) {
u16 mode = 1 << 14;
@ -87,6 +90,26 @@ void Gui__ChangeBrightness() {
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.
void Gui::init(void) {
*(vu16*)0x0400006C |= BIT(14);
@ -97,18 +120,36 @@ void Gui::init(void) {
videoSetMode(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);
vramSetBankB(VRAM_B_MAIN_BG);
vramSetBankC(VRAM_C_SUB_BG);
vramSetBankD(VRAM_D_SUB_SPRITE);
vramSetBankE(VRAM_E_TEX_PALETTE);
vramSetBankF(VRAM_F_TEX_PALETTE_SLOT4);
vramSetBankD(VRAM_D_LCD);
vramSetBankG(VRAM_G_MAIN_SPRITE);
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);
bgSetPriority(bg3Main, 0);
@ -129,7 +170,7 @@ void Gui::init(void) {
// Load back button
tonccpy(gfxSub, arrow_backTiles, arrow_backTilesLen);
tonccpy(SPRITE_PALETTE_SUB, arrow_backPal, arrow_backPalLen);
copyPalette(SPRITE_PALETTE_SUB, arrow_backPal, arrow_backPalLen);
oamSet(&oamSub,
0,
@ -150,7 +191,7 @@ void Gui::init(void) {
gfxSub = oamAllocateGfx(&oamSub, SpriteSize_32x32, SpriteColorFormat_16Color);
tonccpy(gfxSub, cursorTiles, cursorTilesLen);
tonccpy(SPRITE_PALETTE_SUB+16, cursorPal, cursorPalLen);
copyPalette(SPRITE_PALETTE_SUB+16, cursorPal, cursorPalLen);
oamSet(&oamSub,
1,
@ -171,7 +212,7 @@ void Gui::init(void) {
gfxSub = oamAllocateGfx(&oamSub, SpriteSize_64x64, SpriteColorFormat_16Color);
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++) {
oamSet(&oamSub,
@ -236,7 +277,7 @@ void Gui::init(void) {
gfxSub = oamAllocateGfx(&oamSub, SpriteSize_64x64, SpriteColorFormat_16Color);
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++) {
oamSet(&oamSub,
@ -259,7 +300,7 @@ void Gui::init(void) {
gfxSub = oamAllocateGfx(&oamSub, SpriteSize_64x64, SpriteColorFormat_16Color);
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++) {
oamSet(&oamSub,

View File

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

View File

@ -4,6 +4,8 @@
#include "tonccpy.h"
#include "TextEntry.h"
extern u16* colorTable;
FontGraphic smallFont;
FontGraphic largeFont;
@ -24,6 +26,11 @@ void fontInit() {
0xC631,
0xDEF7,
};
if (colorTable) {
for (int i = 1; i < 4; i++) {
palette[i] = colorTable[palette[i]];
}
}
tonccpy(BG_PALETTE, 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) {
extern int bg2Main;
extern int bg3Main;
extern void applyColorLut(u16 *palette, int size);
std::vector<unsigned char> image;
unsigned width, height;
@ -186,6 +187,10 @@ void RocketRobz::Logic(u32 hDown, u32 hHeld, touchPosition touch) {
if ((i % 256) == 255) alternatePixel = !alternatePixel;
alternatePixel = !alternatePixel;
}
applyColorLut(bgGetGfxPtr(bg2Main), 0x18000/sizeof(u16));
if (dsiFeatures()) {
applyColorLut(bgGetGfxPtr(bg3Main), 0x18000/sizeof(u16));
}
graphicLoaded = true;
}
#endif