mirror of
https://github.com/dborth/vbagx.git
synced 2024-11-25 20:16:53 +01:00
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:
parent
b02f07b457
commit
770cfeaec2
@ -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] = {
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -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;
|
||||
|
@ -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
334
source/vba/gb/gbMono.cpp
Normal 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
Loading…
Reference in New Issue
Block a user