GB: gbc color change infrastructure. not hooked up to UI yet

This commit is contained in:
goyuken 2012-11-18 17:02:55 +00:00
parent 40d4253f7a
commit 12844bbd7f
14 changed files with 164 additions and 3 deletions

View File

@ -212,6 +212,7 @@
<Compile Include="Consoles\Intellivision\PSG.cs" />
<Compile Include="Consoles\Intellivision\STIC.cs" />
<Compile Include="Consoles\Nintendo\Gameboy\Gambatte.cs" />
<Compile Include="Consoles\Nintendo\Gameboy\GBColors.cs" />
<Compile Include="Consoles\Nintendo\Gameboy\LibGambatte.cs" />
<Compile Include="Consoles\Nintendo\NES\APU.cs" />
<Compile Include="Consoles\Nintendo\NES\BoardSystem.cs" />

View File

@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Consoles.GB
{
public class GBColors
{
/*
* The GBC uses a RGB555 color space, but it most definately does not resemble sRGB at all.
* To make matters worse, because of the reflective screen, the visible colors depend greatly
* on the viewing environment.
*
* All of these algorithms convert from GBC RGB555 to sRGB RGB888
*/
public struct Triple
{
public int r;
public int g;
public int b;
public Triple(int r, int g, int b)
{
this.r = r;
this.g = g;
this.b = b;
}
public Triple Bit5to8Bad()
{
Triple ret;
ret.r = r * 8;
ret.g = g * 8;
ret.b = b * 8;
return ret;
}
public Triple Bit5to8Good()
{
Triple ret;
ret.r = (r * 255 + 15) / 31;
ret.g = (g * 255 + 15) / 31;
ret.b = (b * 255 + 15) / 31;
return ret;
}
public int ToARGB32()
{
return b | g << 8 | r << 16 | 255 << 24;
}
}
// the version of gambatte in bizhawk
public static Triple GambatteColor(Triple c)
{
Triple ret;
ret.r = (c.r * 13 + c.g * 2 + c.b) >> 1;
ret.g = (c.g * 3 + c.b) << 1;
ret.b = (c.r * 3 + c.g * 2 + c.b * 11) >> 1;
return ret;
}
// vba's default mode
public static Triple VividColor(Triple c)
{
return c.Bit5to8Bad();
}
// "gameboy colors" mode on older versions of VBA
static int gbGetValue(int min, int max, int v)
{
return (int)(min + (float)(max - min) * (2.0 * (v / 31.0) - (v / 31.0) * (v / 31.0)));
}
public static Triple OldVBAColor(Triple c)
{
Triple ret;
ret.r = gbGetValue(gbGetValue(4, 14, c.g),
gbGetValue(24, 29, c.g), c.r) - 4;
ret.g = gbGetValue(gbGetValue(4 + gbGetValue(0, 5, c.r),
14 + gbGetValue(0, 3, c.r), c.b),
gbGetValue(24 + gbGetValue(0, 3, c.r),
29 + gbGetValue(0, 1, c.r), c.b), c.g) - 4;
ret.b = gbGetValue(gbGetValue(4 + gbGetValue(0, 5, c.r),
14 + gbGetValue(0, 3, c.r), c.g),
gbGetValue(24 + gbGetValue(0, 3, c.r),
29 + gbGetValue(0, 1, c.r), c.g), c.b) - 4;
return ret.Bit5to8Bad();
}
// "gameboy colors" mode on newer versions of VBA
public static Triple NewVBAColor(Triple c)
{
Triple ret;
ret.r = (c.r * 13 + c.g * 2 + c.b * 1 + 8) >> 4;
ret.g = (c.r * 1 + c.g * 12 + c.b * 3 + 8) >> 4;
ret.b = (c.r * 2 + c.g * 2 + c.b * 12 + 8) >> 4;
return ret.Bit5to8Bad();
}
}
}

View File

@ -50,7 +50,8 @@ namespace BizHawk.Emulation.Consoles.GB
// set real default colors (before anyone mucks with them at all)
ChangeDMGColors(new int[] { 10798341, 8956165, 1922333, 337157, 10798341, 8956165, 1922333, 337157, 10798341, 8956165, 1922333, 337157 });
SetCGBColors();
InitSound();
Frame = 0;
@ -706,6 +707,21 @@ namespace BizHawk.Emulation.Consoles.GB
LibGambatte.gambatte_setdmgpalettecolor(GambatteState, (LibGambatte.PalType)(i / 4), (uint)i % 4, (uint)colors[i]);
}
void SetCGBColors()
{
int[] lut = new int[32768];
int i = 0;
for (int b = 0; b < 32; b++)
for (int g = 0; g < 32; g++)
for (int r = 0; r < 32; r++)
lut[i++] = GBColors.GambatteColor(new GBColors.Triple(r, g, b)).ToARGB32();
unsafe
{
fixed (int* p = &lut[0])
LibGambatte.gambatte_setcgbpalette(GambatteState, (IntPtr)p);
}
}
#endregion
#region ISoundProvider

View File

@ -98,6 +98,14 @@ namespace BizHawk.Emulation.Consoles.GB
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gambatte_setdmgpalettecolor(IntPtr core, PalType palnum, uint colornum, uint rgb32);
/// <summary>
/// set cgb palette lookup
/// </summary>
/// <param name="core">opaque state pointer</param>
/// <param name="lut">uint32[32768], input color (r,g,b) is at lut[r | g << 5 | b << 10]</param>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gambatte_setcgbpalette(IntPtr core, IntPtr lut);
/// <summary>
/// combination of button flags used by the input callback
/// </summary>

View File

@ -80,6 +80,8 @@ public:
*/
void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32);
void setCgbPalette(unsigned *lut);
/** Sets the callback used for getting input state. */
void setInputGetter(InputGetter *getInput);

View File

@ -45,6 +45,12 @@ __declspec(dllexport) void gambatte_setdmgpalettecolor(void *core, unsigned paln
g->setDmgPaletteColor(palnum, colornum, rgb32);
}
__declspec(dllexport) void gambatte_setcgbpalette(void *core, unsigned *lut)
{
GB *g = (GB *) core;
g->setCgbPalette(lut);
}
class CInputGetter: public InputGetter
{
public:

View File

@ -16,6 +16,8 @@ extern "C"
__declspec(dllexport) void gambatte_setdmgpalettecolor(void *core, unsigned palnum, unsigned colornum, unsigned rgb32);
__declspec(dllexport) void gambatte_setcgbpalette(void *core, unsigned *lut);
__declspec(dllexport) void gambatte_setinputgetter(void *core, unsigned (*getinput)(void));
__declspec(dllexport) void gambatte_setreadcallback(void *core, void (*callback)(unsigned));

View File

@ -110,6 +110,10 @@ public:
void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) {
memory.setDmgPaletteColor(palNum, colorNum, rgb32);
}
void setCgbPalette(unsigned *lut) {
memory.setCgbPalette(lut);
}
void setGameGenie(const std::string &codes) { memory.setGameGenie(codes); }
void setGameShark(const std::string &codes) { memory.setGameShark(codes); }

View File

@ -182,6 +182,10 @@ void GB::setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32)
p_->cpu.setDmgPaletteColor(palNum, colorNum, rgb32);
}
void GB::setCgbPalette(unsigned *lut) {
p_->cpu.setCgbPalette(lut);
}
bool GB::loadState(std::istream &file) {
if (p_->cpu.loaded()) {
// p_->cpu.saveSavedata();

View File

@ -1031,6 +1031,10 @@ void Memory::setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned lon
display.setDmgPaletteColor(palNum, colorNum, rgb32);
}
void Memory::setCgbPalette(unsigned *lut) {
display.setCgbPalette(lut);
}
bool Memory::getMemoryArea(int which, unsigned char **data, int *length) {
if (!data || !length)
return false;

View File

@ -173,6 +173,7 @@ public:
}
void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned long rgb32);
void setCgbPalette(unsigned *lut);
void setGameGenie(const std::string &codes) { cart.setGameGenie(codes); }
void setGameShark(const std::string &codes) { interrupter.setGameShark(codes); }
};

View File

@ -30,12 +30,20 @@ void LCD::setDmgPalette(unsigned long *const palette, const unsigned long *const
palette[3] = dmgColors[data >> 6 & 3];
}
static unsigned long gbcToRgb32(const unsigned bgr15) {
void LCD::setCgbPalette(unsigned *lut) {
for (int i = 0; i < 32768; i++)
cgbColorsRgb32[i] = lut[i];
}
unsigned long LCD::gbcToRgb32(const unsigned bgr15) {
/*
const unsigned long r = bgr15 & 0x1F;
const unsigned long g = bgr15 >> 5 & 0x1F;
const unsigned long b = bgr15 >> 10 & 0x1F;
return ((r * 13 + g * 2 + b) >> 1) << 16 | (g * 3 + b) << 9 | (r * 3 + g * 2 + b * 11) >> 1;
*/
return cgbColorsRgb32[bgr15 & 0x7FFF];
}
/*static unsigned long gbcToRgb16(const unsigned bgr15) {
@ -357,7 +365,7 @@ bool LCD::cgbpAccessible(const unsigned long cycleCounter) {
|| cycleCounter >= m0TimeOfCurrentLine(cycleCounter) + 3 - isDoubleSpeed();
}
static void doCgbColorChange(unsigned char *const pdata,
void LCD::doCgbColorChange(unsigned char *const pdata,
unsigned long *const palette, unsigned index, const unsigned data) {
pdata[index] = data;
index >>= 1;

View File

@ -120,6 +120,7 @@ class LCD {
PPU ppu;
unsigned long dmgColorsRgb32[3 * 4];
unsigned long cgbColorsRgb32[32768];
unsigned char bgpData[8 * 8];
unsigned char objpData[8 * 8];
@ -137,6 +138,9 @@ class LCD {
static void setDmgPalette(unsigned long *palette, const unsigned long *dmgColors, unsigned data);
void setDmgPaletteColor(unsigned index, unsigned long rgb32);
unsigned long gbcToRgb32(const unsigned bgr15);
void doCgbColorChange(unsigned char *const pdata, unsigned long *const palette, unsigned index, const unsigned data);
void refreshPalettes();
void setDBuffer();
@ -160,6 +164,7 @@ public:
void saveState(SaveState &state) const;
void loadState(const SaveState &state, const unsigned char *oamram);
void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned long rgb32);
void setCgbPalette(unsigned *lut);
void setVideoBuffer(uint_least32_t *videoBuf, int pitch);
void setOsdElement(std::auto_ptr<OsdElement> osdElement) { this->osdElement = osdElement; }