Built-in palette support for monochrome gameboy games. Marble Madness, Malibu Beach Volleyball, Metroid 2, Mortal Kombat 1, 2, and 3, Mr Do. etc.

MK3 even changes palettes depending on what character you choose.
This commit is contained in:
Carl.Kenner 2009-04-26 00:05:49 +00:00
parent b02f07b457
commit 770cfeaec2
12 changed files with 546 additions and 49 deletions

View File

@ -2,14 +2,48 @@
* Visual Boy Advance GX
*
* Tantric October 2008
* Carl Kenner April 2009
*
* gamesettings.cpp
*
* Game specific settings, pulled from vba-over.ini
* And palettes for monochrome games, created by Carl Kenner
***************************************************************************/
#include "gamesettings.h"
int gamePalettesCount = 10;
// 0xRRGGBB
// TITLE, 4 Background Colours (brightest to black), 4 Status Bar Colours (brightest to black),
// 3 Sprite 1 Colours (brightest to dark), 3 Sprite 2 Colours (brightest to dark)
gamePalette gamePalettes[10] = {
{"", {0xFFFFFF,0xADADAD,0x636363,0x000000, 0xFFFFFF,0xADADAD,0x636363,0x000000,
0xFFFFFF,0xADADAD,0x636363, 0xFFFFFF,0xADADAD,0x636363}}
,{"MAGNETIC SOCCER", {0x00FF00,0x00AD00,0x006300,0x002000, 0xFFFFFF,0xADADAD,0x636363,0x000000,
0xFF0000,0xAD0000,0x630000, 0x0000FF,0x0000AD,0x000063}}
,{"BEACH,VOLLEYBALL", {0xD4B4A4,0xADAD30,0x000063,0x000020, 0xFFFFFF,0xADADAD,0x636363,0x000000,
0xB49E90,0x00B000,0x31271E, 0x0000FF,0x0000AD,0x000063}}
,{"MARBLE MADNESS", {0x00FFFF,0x00ADAD,0x006363,0x303030, 0xFFFFFF,0xADADAD,0x636363,0x000000,
0xFF0000,0xAD0000,0x630000, 0xFFFF00,0xAD8000,0x634000}}
,{"METROID2", {0xFF7B30,0xAD5230,0x300063,0x000018, 0xFFFFFF,0xADADAD,0x636363,0x000000,
0x7B6300,0xAD0000,0x636363, 0xFF00FF,0x8400AD,0x300063}}
,{"MORTAL KOMBAT", {0xADFF00,0x00AD00,0x006300,0x400000, 0xFFFFFF,0xADADAD,0x636363,0x000000,
0xFFFF00,0xADAD00,0x636300, 0xFFFF00,0xADAD00,0x636300}}
,{"MORTAL KOMBAT II", {0xC0B0FF,0x6890A0,0x303063,0x000000, 0xADFF00,0x00AD00,0x006300,0x400000,
0xC9A104,0xBF5000,0xB20A00, 0x8080FF,0x5050AD,0x303063}}
,{"MORTAL KOMBAT 3", {0xFFFFFF,0x6060A0,0x535373,0x000000, 0xFFFFFF,0xADADAD,0x636363,0x000000,
0xF5CCAC,0x9A7057,0x630000, 0xA87860,0x882020,0x000000}}
,{"MR.DO!", {0x38F038,0x00C800,0x705000,0x600000, 0xFFFFFF,0xADADAD,0x636363,0x000000,
0xFFFFFF,0xADADAD,0x636363, 0xFFFFFF,0xADADAD,0x636363}}
,{"", {0xFFFFFF,0xADADAD,0x636363,0x000000, 0xFFFFFF,0xADADAD,0x636363,0x000000,
0xFFFFFF,0xADADAD,0x636363, 0xFFFFFF,0xADADAD,0x636363}}
};
int gameSettingsCount = 106;
gameSetting gameSettings[106] = {

View File

@ -11,6 +11,8 @@
#ifndef GAMESETTINGS_H
#define GAMESETTINGS_H
#include <gccore.h>
typedef struct gameSetting {
char gameName[100];
char gameID[5];
@ -23,4 +25,12 @@ typedef struct gameSetting {
extern gameSetting gameSettings[];
extern int gameSettingsCount;
typedef struct gamePalette {
char gameName[17];
u32 palette[14]; // in 24-bit 0xRRGGBB
};
extern gamePalette gamePalettes[];
extern int gamePalettesCount;
#endif

View File

@ -31,6 +31,7 @@
#include "gba/GBAinline.h"
void DebugPrintf(const char *format, ...);
void gbSetSpritePal(u8 WhichPal, u32 bright, u32 medium, u32 dark);
#define MK1_CAGE 0
#define MK1_KANO 1
@ -342,6 +343,22 @@ u8 MK3SetSubchar(int Char, int Subchar, u16 OriginalColour) {
return Subchar;
}
void MK3SetPal(int player, u8 NewChar) {
switch (NewChar) {
case MK3_SHEEVA: gbSetSpritePal(player, 0xF5CCAC,0x9A7057,0x800000); break;
case MK3_KANO: gbSetSpritePal(player, 0xA87860,0x882020,0x000000); break;
case MK3_SINDEL: gbSetSpritePal(player, 0xB8B8B8,0x7F5644,0xA818F0); break;
case MK3_SUBZERO: gbSetSpritePal(player, 0xB39890,0x707BFF,0x000020); break;
case MK3_SMOKE: gbSetSpritePal(player, 0xFFFFFF,0xA0A0A0,0x636363); break;
case MK3_CYRAX: gbSetSpritePal(player, 0xC0C0B0,0x90A000,0x303800); break;
case MK3_SEKTOR: gbSetSpritePal(player, 0xA09090,0xC00000,0x300000); break;
case MK3_SONYA: gbSetSpritePal(player, 0xC6A040,0x96964D,0x000000); break;
case MK3_KABAL: gbSetSpritePal(player, 0xB6B6B6,0x866232,0x1A1211); break;
case MK3_SHAOKHAN: gbSetSpritePal(player, 0xC0C0C0,0x7F5644,0x700000); break;
}
return;
}
u32 MK3Input(unsigned short pad) {
OurHealth = gbReadMemory(0xC0D6);
@ -361,12 +378,20 @@ u32 MK3Input(unsigned short pad) {
static u8 OldMenuChar = 0;
// Rumble when they change character
if (MenuChar != OldMenuChar) {
if (InMenu)
if (InMenu) {
systemGameRumble(4);
MK3SetPal(1,MenuChar);
}
OldMenuChar = MenuChar;
}
if (!InMenu) {
switch (OpponentChar) {
MK3SetPal(2, OpponentChar);
}
}
u32 J = GetMKInput(pad);
u32 J = GetMKInput(pad, 1);
if (LK || HK) J |= VBA_BUTTON_A;
if (LP || HP) J |= VBA_BUTTON_B;
if (BL) J |= VBA_BUTTON_START;
@ -419,6 +444,8 @@ u32 MK3Input(unsigned short pad) {
// We just chose a character, so apply anything special here
if (MenuChar==MK3_SUBZERO && MenuSubChar==1)
gbWriteMemory(0xD4CE,MK3_SEKTOR);
else if (MenuChar==MK3_SUBZERO && MenuSubChar==3)
gbWriteMemory(0xD4CE,MK3_SINDEL);
else if (MenuChar==MK3_KANO && MenuSubChar==1)
gbWriteMemory(0xD4CE,MK3_SEKTOR);
else if (MenuChar==MK3_KABAL && MenuSubChar==1)

View File

@ -2568,6 +2568,7 @@ static int MenuSettingsVideo()
sprintf(options.name[i++], "Screen Zoom");
sprintf(options.name[i++], "Screen Position");
sprintf(options.name[i++], "Video Mode");
sprintf(options.name[i++], "Colorize Mono GB");
options.length = i;
GuiText titleTxt("Game Settings - Video", 28, (GXColor){255, 255, 255, 255});
@ -2650,6 +2651,11 @@ static int MenuSettingsVideo()
sprintf (options.value[4], "PAL (60Hz)"); break;
}
if (GCSettings.colorize)
sprintf (options.value[5], "ON");
else
sprintf (options.value[5], "off");
ret = optionBrowser.GetClickedOption();
switch (ret)
@ -2684,6 +2690,11 @@ static int MenuSettingsVideo()
if(GCSettings.videomode > 4)
GCSettings.videomode = 0;
break;
case 5:
if (GCSettings.colorize) GCSettings.colorize = 0;
else GCSettings.colorize = 1;
break;
}
if(backBtn.GetState() == STATE_CLICKED)

View File

@ -140,6 +140,7 @@ preparePrefsData (int method)
createXMLSetting("scaling", "Aspect Ratio Correction", toStr(GCSettings.scaling));
createXMLSetting("xshift", "Horizontal Video Shift", toStr(GCSettings.xshift));
createXMLSetting("yshift", "Vertical Video Shift", toStr(GCSettings.yshift));
createXMLSetting("colorize", "Colorize Mono Gameboy", toStr(GCSettings.colorize));
createXMLSection("Menu", "Menu Settings");
@ -301,6 +302,7 @@ decodePrefsData (int method)
loadXMLSetting(&GCSettings.scaling, "scaling");
loadXMLSetting(&GCSettings.xshift, "xshift");
loadXMLSetting(&GCSettings.yshift, "yshift");
loadXMLSetting(&GCSettings.colorize, "colorize");
// Menu Settings

View File

@ -61,6 +61,8 @@ struct SGCSettings{
int render; // 0 - original, 1 - filtered, 2 - unfiltered
int xshift; // video output shift
int yshift;
int colorize; // colorize Mono Gameboy games
int WiiControls; // Match Wii Game
int WiimoteOrientation;
int ExitAction;

View File

@ -81,6 +81,7 @@ DefaultSettings ()
GCSettings.xshift = 0; // horizontal video shift
GCSettings.yshift = 0; // vertical video shift
GCSettings.colorize = 1; // Colorize mono gameboy games
GCSettings.WiimoteOrientation = 0;
GCSettings.ExitAction = 0;

View File

@ -81,6 +81,14 @@ u16 systemGbPalette[24];
u16 systemColorMap16[0x10000];
u32 *systemColorMap32 = NULL;
void gbSetPalette(u32 RRGGBB[]);
bool StartColorizing();
void StopColorizing();
extern bool ColorizeGameboy;
extern u16 systemMonoPalette[14];
void gbSetBgPal(u8 WhichPal, u32 bright, u32 medium, u32 dark, u32 black=0x000000);
void gbSetSpritePal(u8 WhichPal, u32 bright, u32 medium, u32 dark);
struct EmulatedSystem emulator =
{
NULL,
@ -728,6 +736,7 @@ bool ValidGameId(u32 id)
static void gbApplyPerImagePreferences()
{
char title[17];
// Only works for some GB Colour roms
u8 Colour = gbRom[0x143];
if (Colour == 0x80 || Colour == 0xC0)
@ -740,16 +749,14 @@ static void gbApplyPerImagePreferences()
else
RomIdCode = 0;
// Otherwise we need to make up our own code
title[15] = '\0';
title[16] = '\0';
if (gbRom[0x143] < 0x7F && gbRom[0x143] > 0x20)
strncpy(title, (const char *) &gbRom[0x134], 16);
else
strncpy(title, (const char *) &gbRom[0x134], 15);
if (RomIdCode == 0)
{
char title[17];
title[15] = '\0';
title[16] = '\0';
if (gbRom[0x143] < 0x7F && gbRom[0x143] > 0x20)
strncpy(title, (const char *) &gbRom[0x134], 16);
else
strncpy(title, (const char *) &gbRom[0x134], 15);
//sprintf(DebugStr, "'%s' %x %x %d", title, Colour, gbRom[0x13f] | (gbRom[0x140] << 8) | (gbRom[0x141] << 16) | (gbRom[0x142] << 24), ValidGameId(gbRom[0x13f] | (gbRom[0x140] << 8) | (gbRom[0x141] << 16) | (gbRom[0x142] << 24)));
if (strcmp(title, "ZELDA") == 0)
RomIdCode = LINKSAWAKENING;
else if (strcmp(title, "MORTAL KOMBAT") == 0)
@ -777,6 +784,26 @@ static void gbApplyPerImagePreferences()
else if (strcmp(title, "TMNT3") == 0)
RomIdCode = TMNT3;
}
// look for matching palettes if a monochrome gameboy game
// (or if a Super Gameboy game, but the palette will be ignored later in that case)
int snum = -1;
if ((Colour != 0x80) && (Colour != 0xC0)) {
for(int i=1; i < gamePalettesCount; i++)
{
if(strcmp(title, gamePalettes[i].gameName)==0)
{
snum = i;
break;
}
}
// match found!
if(snum >= 0)
{
gbSetPalette(gamePalettes[snum].palette);
} else {
gbSetPalette(gamePalettes[0].palette);
}
}
}
/****************************************************************************

View File

@ -17,6 +17,10 @@
#define _stricmp strcasecmp
#endif
void gbSetBGPalette(u8 value, bool ColoursChanged=false);
void gbSetObj0Palette(u8 value, bool ColoursChanged=false);
void gbSetObj1Palette(u8 value, bool ColoursChanged=false);
extern u8 *pix;
extern bool speedup;
@ -1202,10 +1206,7 @@ void gbWriteMemory(register u16 address, register u8 value)
else
memset(gbBgpLine,value,sizeof(gbBgpLine));
gbBgp[0] = value & 0x03;
gbBgp[1] = (value & 0x0c)>>2;
gbBgp[2] = (value & 0x30)>>4;
gbBgp[3] = (value & 0xc0)>>6;
gbSetBGPalette(value);
break;
}
@ -1228,10 +1229,7 @@ void gbWriteMemory(register u16 address, register u8 value)
else
memset(gbObp0Line,value,sizeof(gbObp0Line));
gbObp0[0] = value & 0x03;
gbObp0[1] = (value & 0x0c)>>2;
gbObp0[2] = (value & 0x30)>>4;
gbObp0[3] = (value & 0xc0)>>6;
gbSetObj0Palette(value);
break;
}
@ -1254,10 +1252,7 @@ void gbWriteMemory(register u16 address, register u8 value)
else
memset(gbObp1Line,value,sizeof(gbObp1Line));
gbObp1[0] = value & 0x03;
gbObp1[1] = (value & 0x0c)>>2;
gbObp1[2] = (value & 0x30)>>4;
gbObp1[3] = (value & 0xc0)>>6;
gbSetObj1Palette(value);
break;
}
@ -2558,12 +2553,12 @@ void gbReset()
}
} else {
if(gbSgbMode) {
for(int i = 0; i < 8; i++)
gbPalette[i] = systemGbPalette[gbPaletteOption*8+i];
for(int i = 0; i < 12; i++)
gbPalette[i] = systemGbPalette[gbPaletteOption*12+i];
}
for(int i = 0; i < 8; i++)
gbPalette[i] = systemGbPalette[gbPaletteOption*8+i];
for(int i = 0; i < 12; i++)
gbPalette[i] = systemGbPalette[gbPaletteOption*12+i];
}
GBTIMER_MODE_0_CLOCK_TICKS = 256;

View File

@ -4,6 +4,11 @@
#include "gbGlobals.h"
#include "gbSGB.h"
void gbSetBGPalette(u8 value, bool ColoursChanged=false);
void gbSetObj0Palette(u8 value, bool ColoursChanged=false);
void gbSetObj1Palette(u8 value, bool ColoursChanged=false);
extern bool ColorizeGameboy;
u8 gbInvertTab[256] = {
0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0,
0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0,
@ -46,6 +51,7 @@ extern int layerSettings;
void gbRenderLine()
{
static u8 oldBgPal=0;
memset(gbLineMix, 0, sizeof(gbLineMix));
u8 * bank0;
u8 * bank1;
@ -141,8 +147,11 @@ void gbRenderLine()
if(gbCgbMode) {
c = c + (attrs & 7)*4;
} else {
c = (gbBgpLine[x+(gbSpeed ? 5 : 11)+SpritesTicks]>>(c<<1)) &3;
if(gbSgbMode && !gbCgbMode) {
// Get the background palette to use (from the delayed pipeline)
u8 BgPal = gbBgpLine[x+(gbSpeed ? 5 : 11)+SpritesTicks];
// Super Game Boy has its own special palettes
if(gbSgbMode) {
c = (BgPal>>(c<<1)) &3;
int dx = x >> 3;
int dy = y >> 3;
@ -152,7 +161,15 @@ void gbRenderLine()
palette = 0;
c = c + 4*palette;
}
// Mono Game Boy requires special palette handling
} else {
if (BgPal!=oldBgPal) {
gbSetBGPalette(BgPal);
oldBgPal = BgPal;
}
if (!ColorizeGameboy) c = (BgPal>>(c<<1)) &3;
else c += 0;
}
}
gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] :
gbPalette[c] & 0x7FFF;
@ -205,9 +222,15 @@ void gbRenderLine()
{
u16 color = gbColorOption ? gbColorFilter[0x7FFF] :
0x7FFF;
if (!gbCgbMode)
color = gbColorOption ? gbColorFilter[gbPalette[gbBgpLine[i+(gbSpeed ? 5 : 11)+gbSpritesTicks[i]*(gbSpeed ? 2 : 4)]&3] & 0x7FFF] :
gbPalette[gbBgpLine[i+(gbSpeed ? 5 : 11)+gbSpritesTicks[i]*(gbSpeed ? 2 : 4)]&3] & 0x7FFF;
if (!gbCgbMode) {
// Get the background palette to use (from the delayed pipeline)
u8 BgPal = gbBgpLine[i+(gbSpeed ? 5 : 11)+gbSpritesTicks[i]*(gbSpeed ? 2 : 4)];
if ((BgPal!=oldBgPal) && !gbSgbMode) {
gbSetBGPalette(BgPal);
oldBgPal = BgPal;
}
color = gbColorOption ? gbColorFilter[gbPalette[BgPal&3] & 0x7FFF] : gbPalette[BgPal&3] & 0x7FFF;
}
gbLineMix[i] = color;
gbLineBuffer[i] = 0;
}
@ -338,8 +361,11 @@ void gbRenderLine()
if(gbCgbMode) {
c = c + (attrs & 7) * 4;
} else {
c = (gbBgpLine[x+(gbSpeed ? 5 : 11)+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)]>>(c<<1)) &3;
if(gbSgbMode && !gbCgbMode) {
// Get the background palette to use (from the delayed pipeline)
u8 BgPal = gbBgpLine[x+(gbSpeed ? 5 : 11)+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)];
// Super Game Boy has its own special palettes
if(gbSgbMode) {
c = (BgPal>>(c<<1)) &3;
int dx = x >> 3;
int dy = y >> 3;
@ -349,7 +375,15 @@ void gbRenderLine()
palette = 0;
c = c + 4*palette;
}
// Mono Game Boy requires special palette handling
} else {
if (BgPal!=oldBgPal) {
gbSetBGPalette(BgPal);
oldBgPal = BgPal;
}
if (!ColorizeGameboy) c = (BgPal>>(c<<1)) &3;
else c += 4;
}
}
gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] :
gbPalette[c] & 0x7FFF;
@ -405,6 +439,7 @@ void gbRenderLine()
void gbDrawSpriteTile(int tile, int x,int y,int t, int flags,
int size,int spriteNumber)
{
static u8 oldObj0Pal=0, oldObj1Pal=0;
u8 * bank0;
u8 * bank1;
if(gbCgbMode) {
@ -422,19 +457,35 @@ void gbDrawSpriteTile(int tile, int x,int y,int t, int flags,
int init = 0x0000;
for (int i = 0; i<4; i++)
{
gbObp0[i] = (gbObp0Line[x+11+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)]>>(i<<1)) & 3;
gbObp1[i] = (gbObp1Line[x+11+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)]>>(i<<1)) & 3;
// The monochrome gameboy has 2 sprite palettes, because each palette only contains 3 colours
// out of a possible 4. Here we are colourising the two palettes seperately.
u8 *pal;
u8 ObjPal = 0;
u8 PalOffset = 8;
if(!gbCgbMode) {
if(flags & 0x10) {
pal = gbObp1;
ObjPal = gbObp1Line[x+11+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)];
if (ObjPal!=oldObj1Pal && !gbSgbMode) {
gbSetObj1Palette(ObjPal);
oldObj1Pal = ObjPal;
}
PalOffset = 12;
} else {
pal = gbObp0;
ObjPal = gbObp0Line[x+11+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)];
if (ObjPal!=oldObj0Pal && !gbSgbMode) {
gbSetObj0Palette(ObjPal);
oldObj0Pal = ObjPal;
}
PalOffset = 8;
}
}
u8 *pal = gbObp0;
int flipx = (flags & 0x20);
int flipy = (flags & 0x40);
if((flags & 0x10))
pal = gbObp1;
if(flipy) {
t = (size ? 15 : 7) - t;
}
@ -461,6 +512,7 @@ void gbDrawSpriteTile(int tile, int x,int y,int t, int flags,
if( (b & mask))
c+=2;
// colour index 0 is always transparent, so skip
if(c==0) continue;
int xxx = xx+x;
@ -508,9 +560,9 @@ void gbDrawSpriteTile(int tile, int x,int y,int t, int flags,
if(gbCgbMode) {
c = c + (flags & 0x07)*4 + 32;
} else {
c = pal[c];
if(gbSgbMode && !gbCgbMode) {
// Super Game Boy has its own special palettes
if(gbSgbMode) {
c = (ObjPal>>(c<<1)) &3;
int dx = xxx >> 3;
int dy = y >> 3;
@ -520,8 +572,10 @@ void gbDrawSpriteTile(int tile, int x,int y,int t, int flags,
palette = 0;
c = c + 4*palette;
} else {
c += 4;
// Monochrome Game Boy
} else {
if (!ColorizeGameboy) c = (ObjPal>>(c<<1)) &3;
else c += PalOffset;
}
}

334
source/vba/gb/gbMono.cpp Normal file
View File

@ -0,0 +1,334 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../System.h"
#include "../NLS.h"
#include "gb.h"
#include "gbCheats.h"
#include "gbGlobals.h"
#include "vba.h"
#include "../ngc/menu.h"
bool ColorizeGameboy = true;
// The 14-colour palette for a monochrome gameboy game
// bg black, bg dark, bg light, bg white, window black, window dark, window light, window white,
// obj0 dark, obj0 light, obj0 white, obj1 dark, obj1 light, obj1 white
// Only the user sets these colours from emulator menu, and it is only read
// by the palette setting functions.
u16 systemMonoPalette[14];
// quickly map the 12 possible indices to 15-bit colours
// bg index 0..3, obj0 index 0..3, obj1 index 0..3
// This is set internally by the palette setting functions, and used by the
// drawing functions.
//u16 gbPalette[12];
const float BL[4] = {0.1f, 0.4f, 0.7f, 1.0f};
u16 changeColourBrightness(u16 rgb, float factor) {
if (factor==1.0f) return rgb;
int bonus = 0;
int r = (rgb & 0x1f);
r = r * factor;
if (r>31) {
r=31;
bonus+=(r-30)/2;
}
int g = ((rgb >> 5) & 0x1f);
g = g * factor;
if (g>31) {
g=31;
bonus+=(g-30)/2;
}
int b = ((rgb >> 10) & 0x1f);
b = b * factor;
if (b>31) {
b=31;
bonus+=(b-30)/2;
}
r+=bonus;
g+=bonus;
b+=bonus;
if (r>31) r=31;
if (g>31) g=31;
if (b>31) b=31;
return r | (g << 5) | (b << 10);
}
u8 oldBgp = 0xFC;
// Sets the brightnesses of both the background and window palettes
void gbSetBGPalette(u8 value, bool ColoursChanged=false) {
static u8 DarkestToBrightestIndex[4] = {3, 2, 1, 0};
static u8 Darkness[4] = {0, 1, 2, 3};
static float BrightnessForBrightest=1, BrightnessForDarkest=0.1; // brightness of palette when indexes are right
// darkness of each index (0 = white, 3 = black)
gbBgp[0] = value & 0x03;
gbBgp[1] = (value & 0x0c)>>2;
gbBgp[2] = (value & 0x30)>>4;
gbBgp[3] = (value & 0xc0)>>6;
if ((value==oldBgp && !ColoursChanged) || gbSgbMode || !ColorizeGameboy) return;
// check for duplicates
bool dup = false;
for (int i=0; i<=2; i++)
for (int j=i+1; j<=3; j++)
if (gbBgp[i]==gbBgp[j]) {
dup=true;
break;
}
if (!dup) { // no duplicates, therefore a complete palette change
// now we need to map them from darkest to brightest
int Colour = 0;
for (int darkness = 3; darkness>=0; darkness--) {
for (int index=0; index<=3; index++) {
if (gbBgp[index]==darkness) {
DarkestToBrightestIndex[Colour]=index;
Darkness[Colour]=gbBgp[index];
Colour++;
break;
}
}
}
// brightness of brightest colour
BrightnessForBrightest = BL[3-gbBgp[DarkestToBrightestIndex[3]]];
BrightnessForDarkest = BL[3-gbBgp[DarkestToBrightestIndex[0]]];
} else { // duplicates implies fading in or out
// since we are really trying to fade, not change palette,
// rely on previous DarkestToBrightest list
}
float NewBrightnessForBrightest = BL[3-gbBgp[DarkestToBrightestIndex[3]]];
float BrightnessFactor;
// check if they are trying to make the palette brighter
if (NewBrightnessForBrightest==1.0f && BrightnessForBrightest==1.0f) {
float NewBrightnessForDarkest = BL[3-gbBgp[DarkestToBrightestIndex[0]]];
BrightnessFactor = NewBrightnessForDarkest/BrightnessForDarkest;
} else {
BrightnessFactor = NewBrightnessForBrightest/BrightnessForBrightest;
}
// BG colours
for (int colour = 0; colour <= 3; colour++) {
u16 colourRGB = systemMonoPalette[colour];
float colourBrightness = BL[colour];
float indexBrightness = BL[3-Darkness[colour]]*BrightnessFactor;
gbPalette[0+DarkestToBrightestIndex[colour]] = changeColourBrightness(colourRGB, indexBrightness/colourBrightness);
}
// Window colours
for (int colour = 0; colour <= 3; colour++) {
u16 colourRGB = systemMonoPalette[4+colour];
float colourBrightness = BL[colour];
float indexBrightness = BL[3-Darkness[colour]]*BrightnessFactor;
gbPalette[4+DarkestToBrightestIndex[colour]] = changeColourBrightness(colourRGB, indexBrightness/colourBrightness);
}
}
u8 oldObp0 = 0xFF;
void gbSetObj0Palette(u8 value, bool ColoursChanged = false) {
static u8 DarkestToBrightestIndex[3] = {3, 2, 1};
static u8 Darkness[3] = {1, 2, 3};
static float BrightnessForBrightest, BrightnessForDarkest; // brightness of palette when indexes are right
// darkness of each index (0 = white, 3 = black)
gbObp0[0] = value & 0x03;
gbObp0[1] = (value & 0x0c)>>2;
gbObp0[2] = (value & 0x30)>>4;
gbObp0[3] = (value & 0xc0)>>6;
if ((value==oldObp0 && !ColoursChanged) || gbSgbMode || !ColorizeGameboy) return;
// check for duplicates
bool dup = false;
for (int i=1; i<=2; i++)
for (int j=i+1; j<=3; j++)
if (gbObp0[i]==gbObp0[j]) {
dup=true;
break;
}
if (!dup) { // no duplicates, therefore a complete palette change
// now we need to map them from darkest to brightest
int Colour = 0;
for (int darkness = 3; darkness>=0; darkness--) {
for (int index=1; index<=3; index++) {
if (gbObp0[index]==darkness) {
DarkestToBrightestIndex[Colour]=index;
Darkness[Colour]=gbObp0[index];
Colour++;
break;
}
}
}
// brightness of brightest colour
BrightnessForBrightest = BL[3-gbObp0[DarkestToBrightestIndex[2]]];
BrightnessForDarkest = BL[3-gbObp0[DarkestToBrightestIndex[0]]];
} else { // duplicates implies fading in or out
// since we are really trying to fade, not change palette,
// rely on previous DarkestToBrightest list
}
float NewBrightnessForBrightest = BL[3-gbObp0[DarkestToBrightestIndex[2]]];
float BrightnessFactor;
// check if they are trying to make the palette brighter
if (NewBrightnessForBrightest==1.0f && BrightnessForBrightest==1.0f) {
float NewBrightnessForDarkest = BL[3-gbObp0[DarkestToBrightestIndex[0]]];
BrightnessFactor = NewBrightnessForDarkest/BrightnessForDarkest;
} else {
BrightnessFactor = NewBrightnessForBrightest/BrightnessForBrightest;
}
for (int colour = 0; colour <= 2; colour++) {
u16 colourRGB = systemMonoPalette[colour+8];
float colourBrightness = BL[colour+1];
float indexBrightness = BL[3-Darkness[colour]]*BrightnessFactor;
gbPalette[8+DarkestToBrightestIndex[colour]] = changeColourBrightness(colourRGB, indexBrightness/colourBrightness);
}
gbPalette[8] = 0; // always transparent
}
u8 oldObp1 = 0xFF;
void gbSetObj1Palette(u8 value, bool ColoursChanged = false) {
static u8 DarkestToBrightestIndex[3] = {3, 2, 1};
static u8 Darkness[3] = {1, 2, 3};
static float BrightnessForBrightest, BrightnessForDarkest; // brightness of palette when indexes are right
// darkness of each index (0 = white, 3 = black)
gbObp1[0] = value & 0x03;
gbObp1[1] = (value & 0x0c)>>2;
gbObp1[2] = (value & 0x30)>>4;
gbObp1[3] = (value & 0xc0)>>6;
if ((value==oldObp1 && !ColoursChanged) || gbSgbMode || !ColorizeGameboy) return;
// check for duplicates
bool dup = false;
for (int i=1; i<=2; i++)
for (int j=i+1; j<=3; j++)
if (gbObp1[i]==gbObp1[j]) {
dup=true;
break;
}
if (!dup) { // no duplicates, therefore a complete palette change
// now we need to map them from darkest to brightest
int Colour = 0;
for (int darkness = 3; darkness>=0; darkness--) {
for (int index=1; index<=3; index++) {
if (gbObp1[index]==darkness) {
DarkestToBrightestIndex[Colour]=index;
Darkness[Colour]=gbObp1[index];
Colour++;
break;
}
}
}
// brightness of brightest colour
BrightnessForBrightest = BL[3-gbObp1[DarkestToBrightestIndex[2]]];
BrightnessForDarkest = BL[3-gbObp1[DarkestToBrightestIndex[0]]];
} else { // duplicates implies fading in or out
// since we are really trying to fade, not change palette,
// rely on previous DarkestToBrightest list
}
float NewBrightnessForBrightest = BL[3-gbObp1[DarkestToBrightestIndex[2]]];
float BrightnessFactor;
// check if they are trying to make the palette brighter
if (NewBrightnessForBrightest==1.0f && BrightnessForBrightest==1.0f) {
float NewBrightnessForDarkest = BL[3-gbObp1[DarkestToBrightestIndex[0]]];
BrightnessFactor = NewBrightnessForDarkest/BrightnessForDarkest;
} else {
BrightnessFactor = NewBrightnessForBrightest/BrightnessForBrightest;
}
for (int colour = 0; colour <= 2; colour++) {
u16 colourRGB = systemMonoPalette[colour+11];
float colourBrightness = BL[colour+1];
float indexBrightness = BL[3-Darkness[colour]]*BrightnessFactor;
gbPalette[12+DarkestToBrightestIndex[colour]] = changeColourBrightness(colourRGB, indexBrightness/colourBrightness);
}
gbPalette[12] = 0; // always transparent
}
bool StartColorizing() {
if ((!GCSettings.colorize) || gbSgbMode || gbCgbMode) return false;
if (ColorizeGameboy) return true;
ColorizeGameboy = true;
gbSetBGPalette(oldBgp);
gbSetObj0Palette(oldObp0);
gbSetObj1Palette(oldObp1);
return true;
}
void StopColorizing() {
for(int i = 0; i < 8; i++) // CAKTODO fix
gbPalette[i] = systemGbPalette[gbPaletteOption*8+i];
ColorizeGameboy = false;
}
// convert 0xRRGGBB to our 15 bit format
u16 Make15Bit(u32 rgb) {
return ((rgb >> 19) & 0x1F) | (((rgb >> 11) & 0x1F) << 5) | (((rgb >> 3) & 0x1F) << 10);
}
void gbSetSpritePal(u8 WhichPal, u32 bright, u32 medium, u32 dark) {
if (!StartColorizing()) return;
int index = 0;
if (WhichPal==0) {
gbSetSpritePal(1, bright, medium, dark);
gbSetSpritePal(2, bright, medium, dark);
return;
} else if (WhichPal==1) index = 8; // Obj0
else if (WhichPal==2) index=11; // Obj1
systemMonoPalette[index]=Make15Bit(dark);
systemMonoPalette[index+1]=Make15Bit(medium);
systemMonoPalette[index+2]=Make15Bit(bright);
if (WhichPal==1) {
u8 old = oldObp0;
oldObp0 +=1;
gbSetObj0Palette(old);
} else if (WhichPal==2) {
u8 old = oldObp1;
oldObp1 +=1;
gbSetObj1Palette(old);
}
}
void gbSetSpritePal(u8 WhichPal, u32 bright) {
u8 r = (bright >> 16) & 0xFF;
u8 g = (bright >> 8) & 0xFF;
u8 b = (bright >> 0) & 0xFF;
u32 medium = (((u32)(r*0.7f)) << 16) | (((u32)(g*0.7f)) << 8) | (((u32)(b*0.7f)) << 0);
u32 dark = (((u32)(r*0.4f)) << 16) | (((u32)(g*0.4f)) << 8) | (((u32)(b*0.4f)) << 0);
gbSetSpritePal(WhichPal, bright, medium, dark);
}
void gbSetBgPal(u8 WhichPal, u32 bright, u32 medium, u32 dark, u32 black=0x000000) {
if (!StartColorizing()) return;
int index = 0;
if (WhichPal==0) {
gbSetBgPal(1, bright, medium, dark, black);
gbSetBgPal(2, bright, medium, dark, black);
return;
} else if (WhichPal==1) index = 0; // background
else if (WhichPal==2) index=4; // window
systemMonoPalette[index]=Make15Bit(black);
systemMonoPalette[index+1]=Make15Bit(dark);
systemMonoPalette[index+2]=Make15Bit(medium);
systemMonoPalette[index+3]=Make15Bit(bright);
gbSetBGPalette(oldBgp, true);
}
void gbSetBgPal(u8 WhichPal, u32 bright) {
u8 r = (bright >> 16) & 0xFF;
u8 g = (bright >> 8) & 0xFF;
u8 b = (bright >> 0) & 0xFF;
u32 medium = (((u32)(r*0.7f)) << 16) | (((u32)(g*0.7f)) << 8) | (((u32)(b*0.7f)) << 0);
u32 dark = (((u32)(r*0.4f)) << 16) | (((u32)(g*0.4f)) << 8) | (((u32)(b*0.4f)) << 0);
u32 black = (((u32)(r*0.1f)) << 16) | (((u32)(g*0.1f)) << 8) | (((u32)(b*0.1f)) << 0);
gbSetBgPal(WhichPal, bright, medium, dark, black);
}
// Set the whole 14-colour palette
void gbSetPalette(u32 RRGGBB[]) {
gbSetBgPal(1, RRGGBB[0], RRGGBB[1], RRGGBB[2], RRGGBB[3]);
gbSetBgPal(2, RRGGBB[4], RRGGBB[5], RRGGBB[6], RRGGBB[7]);
gbSetSpritePal(1, RRGGBB[8], RRGGBB[9], RRGGBB[10]);
gbSetSpritePal(2, RRGGBB[11], RRGGBB[12], RRGGBB[13]);
}

File diff suppressed because one or more lines are too long