diff --git a/desmume/src/OGLRender.h b/desmume/src/OGLRender.h
index 596b3a28f..8729c6db5 100755
--- a/desmume/src/OGLRender.h
+++ b/desmume/src/OGLRender.h
@@ -301,7 +301,7 @@ enum OGLVertexAttributeID
{
OGLVertexAttributeID_Position = 0,
OGLVertexAttributeID_TexCoord0 = 8,
- OGLVertexAttributeID_Color = 3,
+ OGLVertexAttributeID_Color = 3
};
enum OGLTextureUnitID
diff --git a/desmume/src/frontend/cocoa/ClientDisplayView.cpp b/desmume/src/frontend/cocoa/ClientDisplayView.cpp
index 52e3a2361..af41b1dc7 100644
--- a/desmume/src/frontend/cocoa/ClientDisplayView.cpp
+++ b/desmume/src/frontend/cocoa/ClientDisplayView.cpp
@@ -93,6 +93,13 @@ void ClientDisplayView::__InstanceInit(const ClientDisplayViewProperties &props)
_showCPULoadAverage = false;
_showRTC = false;
+ _hudColorVideoFPS = 0xFFFFFFFF;
+ _hudColorRender3DFPS = 0xFFFFFFFF;
+ _hudColorFrameIndex = 0xFFFFFFFF;
+ _hudColorLagFrameCount = 0xFFFFFFFF;
+ _hudColorCPULoadAverage = 0xFFFFFFFF;
+ _hudColorRTC = 0xFFFFFFFF;
+
_clientFrameInfo.videoFPS = 0;
_ndsFrameInfo.clear();
@@ -560,6 +567,102 @@ void ClientDisplayView::SetHUDShowRTC(const bool visibleState)
this->UpdateView();
}
+uint32_t ClientDisplayView::GetHUDColorVideoFPS() const
+{
+ return this->_hudColorVideoFPS;
+}
+
+void ClientDisplayView::SetHUDColorVideoFPS(uint32_t color32)
+{
+ this->_hudColorVideoFPS = color32;
+
+ pthread_mutex_lock(&this->_mutexHUDString);
+ this->_hudNeedsUpdate = true;
+ pthread_mutex_unlock(&this->_mutexHUDString);
+
+ this->UpdateView();
+}
+
+uint32_t ClientDisplayView::GetHUDColorRender3DFPS() const
+{
+ return this->_hudColorRender3DFPS;
+}
+
+void ClientDisplayView::SetHUDColorRender3DFPS(uint32_t color32)
+{
+ this->_hudColorRender3DFPS = color32;
+
+ pthread_mutex_lock(&this->_mutexHUDString);
+ this->_hudNeedsUpdate = true;
+ pthread_mutex_unlock(&this->_mutexHUDString);
+
+ this->UpdateView();
+}
+
+uint32_t ClientDisplayView::GetHUDColorFrameIndex() const
+{
+ return this->_hudColorFrameIndex;
+}
+
+void ClientDisplayView::SetHUDColorFrameIndex(uint32_t color32)
+{
+ this->_hudColorFrameIndex = color32;
+
+ pthread_mutex_lock(&this->_mutexHUDString);
+ this->_hudNeedsUpdate = true;
+ pthread_mutex_unlock(&this->_mutexHUDString);
+
+ this->UpdateView();
+}
+
+uint32_t ClientDisplayView::GetHUDColorLagFrameCount() const
+{
+ return this->_hudColorLagFrameCount;
+}
+
+void ClientDisplayView::SetHUDColorLagFrameCount(uint32_t color32)
+{
+ this->_hudColorLagFrameCount = color32;
+
+ pthread_mutex_lock(&this->_mutexHUDString);
+ this->_hudNeedsUpdate = true;
+ pthread_mutex_unlock(&this->_mutexHUDString);
+
+ this->UpdateView();
+}
+
+uint32_t ClientDisplayView::GetHUDColorCPULoadAverage() const
+{
+ return this->_hudColorCPULoadAverage;
+}
+
+void ClientDisplayView::SetHUDColorCPULoadAverage(uint32_t color32)
+{
+ this->_hudColorCPULoadAverage = color32;
+
+ pthread_mutex_lock(&this->_mutexHUDString);
+ this->_hudNeedsUpdate = true;
+ pthread_mutex_unlock(&this->_mutexHUDString);
+
+ this->UpdateView();
+}
+
+uint32_t ClientDisplayView::GetHUDColorRTC() const
+{
+ return this->_hudColorRTC;
+}
+
+void ClientDisplayView::SetHUDColorRTC(uint32_t color32)
+{
+ this->_hudColorRTC = color32;
+
+ pthread_mutex_lock(&this->_mutexHUDString);
+ this->_hudNeedsUpdate = true;
+ pthread_mutex_unlock(&this->_mutexHUDString);
+
+ this->UpdateView();
+}
+
bool ClientDisplayView::HUDNeedsUpdate()
{
pthread_mutex_lock(&this->_mutexHUDString);
@@ -1186,7 +1289,7 @@ void ClientDisplay3DView::SetSourceDeposterize(bool useDeposterize)
this->_useDeposterize = (this->_canFilterOnGPU) ? useDeposterize : false;
}
-void ClientDisplay3DView::SetHUDVertices(float viewportWidth, float viewportHeight, float *vtxBufferPtr)
+void ClientDisplay3DView::SetHUDPositionVertices(float viewportWidth, float viewportHeight, float *vtxPositionBufferPtr)
{
pthread_mutex_lock(&this->_mutexHUDString);
std::string hudString = this->_hudString;
@@ -1203,10 +1306,10 @@ void ClientDisplay3DView::SetHUDVertices(float viewportWidth, float viewportHeig
// First, calculate the vertices of the text box.
// The text box should always be the first character in the string.
- vtxBufferPtr[0] = 0.0f; vtxBufferPtr[1] = 0.0f;
- vtxBufferPtr[2] = charLocX; vtxBufferPtr[3] = 0.0f;
- vtxBufferPtr[4] = charLocX; vtxBufferPtr[5] = -textBoxTextOffset;
- vtxBufferPtr[6] = 0.0f; vtxBufferPtr[7] = -textBoxTextOffset;
+ vtxPositionBufferPtr[0] = 0.0f; vtxPositionBufferPtr[1] = 0.0f;
+ vtxPositionBufferPtr[2] = charLocX; vtxPositionBufferPtr[3] = 0.0f;
+ vtxPositionBufferPtr[4] = charLocX; vtxPositionBufferPtr[5] = -textBoxTextOffset;
+ vtxPositionBufferPtr[6] = 0.0f; vtxPositionBufferPtr[7] = -textBoxTextOffset;
// Calculate the vertices of the remaining characters in the string.
for (size_t i = 1, j = 8; i < length; i++, j+=8)
@@ -1220,8 +1323,8 @@ void ClientDisplay3DView::SetHUDVertices(float viewportWidth, float viewportHeig
textBoxWidth = charLocX;
}
- vtxBufferPtr[5] -= lineHeight;
- vtxBufferPtr[7] -= lineHeight;
+ vtxPositionBufferPtr[5] -= lineHeight;
+ vtxPositionBufferPtr[7] -= lineHeight;
charLocX = textBoxTextOffset;
charLocY -= lineHeight;
@@ -1230,10 +1333,10 @@ void ClientDisplay3DView::SetHUDVertices(float viewportWidth, float viewportHeig
const float charWidth = this->_glyphInfo[c].width * charSize / (float)this->_glyphTileSize;
- vtxBufferPtr[j+0] = charLocX; vtxBufferPtr[j+1] = charLocY + charSize; // Top Left
- vtxBufferPtr[j+2] = charLocX + charWidth; vtxBufferPtr[j+3] = charLocY + charSize; // Top Right
- vtxBufferPtr[j+4] = charLocX + charWidth; vtxBufferPtr[j+5] = charLocY; // Bottom Right
- vtxBufferPtr[j+6] = charLocX; vtxBufferPtr[j+7] = charLocY; // Bottom Left
+ vtxPositionBufferPtr[j+0] = charLocX; vtxPositionBufferPtr[j+1] = charLocY + charSize; // Top Left
+ vtxPositionBufferPtr[j+2] = charLocX + charWidth; vtxPositionBufferPtr[j+3] = charLocY + charSize; // Top Right
+ vtxPositionBufferPtr[j+4] = charLocX + charWidth; vtxPositionBufferPtr[j+5] = charLocY; // Bottom Right
+ vtxPositionBufferPtr[j+6] = charLocX; vtxPositionBufferPtr[j+7] = charLocY; // Bottom Left
charLocX += (charWidth + (charSize * 0.03f) + 0.10f);
}
@@ -1258,19 +1361,122 @@ void ClientDisplay3DView::SetHUDVertices(float viewportWidth, float viewportHeig
boxOffset *= this->_scaleFactor;
// Set the width of the text box
- vtxBufferPtr[2] += textBoxWidth;
- vtxBufferPtr[4] += textBoxWidth;
+ vtxPositionBufferPtr[2] += textBoxWidth;
+ vtxPositionBufferPtr[4] += textBoxWidth;
// Scale and translate the box
for (size_t i = 0; i < (length * 8); i+=2)
{
// Scale
- vtxBufferPtr[i+0] *= textBoxScale;
- vtxBufferPtr[i+1] *= textBoxScale;
+ vtxPositionBufferPtr[i+0] *= textBoxScale;
+ vtxPositionBufferPtr[i+1] *= textBoxScale;
// Translate
- vtxBufferPtr[i+0] += boxOffset - (viewportWidth / 2.0f);
- vtxBufferPtr[i+1] += (viewportHeight / 2.0f) - boxOffset;
+ vtxPositionBufferPtr[i+0] += boxOffset - (viewportWidth / 2.0f);
+ vtxPositionBufferPtr[i+1] += (viewportHeight / 2.0f) - boxOffset;
+ }
+}
+
+void ClientDisplay3DView::SetHUDColorVertices(uint32_t *vtxColorBufferPtr)
+{
+ pthread_mutex_lock(&this->_mutexHUDString);
+ std::string hudString = this->_hudString;
+ pthread_mutex_unlock(&this->_mutexHUDString);
+
+ const char *cString = hudString.c_str();
+ const size_t length = hudString.length();
+ uint32_t currentColor = 0x40000000;
+
+ // First, calculate the color of the text box.
+ // The text box should always be the first character in the string.
+ vtxColorBufferPtr[0] = currentColor;
+ vtxColorBufferPtr[1] = currentColor;
+ vtxColorBufferPtr[2] = currentColor;
+ vtxColorBufferPtr[3] = currentColor;
+
+ // Calculate the colors of the remaining characters in the string.
+ bool alreadyColoredVideoFPS = false;
+ bool alreadyColoredRender3DFPS = false;
+ bool alreadyColoredFrameIndex = false;
+ bool alreadyColoredLagFrameCount = false;
+ bool alreadyColoredCPULoadAverage = false;
+ bool alreadyColoredRTC = false;
+
+ if (this->_showVideoFPS)
+ {
+ currentColor = this->_hudColorVideoFPS;
+ alreadyColoredVideoFPS = true;
+ }
+ else if (this->_showRender3DFPS)
+ {
+ currentColor = this->_hudColorRender3DFPS;
+ alreadyColoredRender3DFPS = true;
+ }
+ else if (this->_showFrameIndex)
+ {
+ currentColor = this->_hudColorFrameIndex;
+ alreadyColoredFrameIndex = true;
+ }
+ else if (this->_showLagFrameCount)
+ {
+ currentColor = this->_hudColorLagFrameCount;
+ alreadyColoredLagFrameCount = true;
+ }
+ else if (this->_showCPULoadAverage)
+ {
+ currentColor = this->_hudColorCPULoadAverage;
+ alreadyColoredCPULoadAverage = true;
+ }
+ else if (this->_showRTC)
+ {
+ currentColor = this->_hudColorRTC;
+ alreadyColoredRTC = true;
+ }
+
+ for (size_t i = 1, j = 4; i < length; i++, j+=4)
+ {
+ const char c = cString[i];
+
+ if (c == '\n')
+ {
+ if (this->_showVideoFPS && !alreadyColoredVideoFPS)
+ {
+ currentColor = this->_hudColorVideoFPS;
+ alreadyColoredVideoFPS = true;
+ }
+ else if (this->_showRender3DFPS && !alreadyColoredRender3DFPS)
+ {
+ currentColor = this->_hudColorRender3DFPS;
+ alreadyColoredRender3DFPS = true;
+ }
+ else if (this->_showFrameIndex && !alreadyColoredFrameIndex)
+ {
+ currentColor = this->_hudColorFrameIndex;
+ alreadyColoredFrameIndex = true;
+ }
+ else if (this->_showLagFrameCount && !alreadyColoredLagFrameCount)
+ {
+ currentColor = this->_hudColorLagFrameCount;
+ alreadyColoredLagFrameCount = true;
+ }
+ else if (this->_showCPULoadAverage && !alreadyColoredCPULoadAverage)
+ {
+ currentColor = this->_hudColorCPULoadAverage;
+ alreadyColoredCPULoadAverage = true;
+ }
+ else if (this->_showRTC && !alreadyColoredRTC)
+ {
+ currentColor = this->_hudColorRTC;
+ alreadyColoredRTC = true;
+ }
+
+ continue;
+ }
+
+ vtxColorBufferPtr[j+0] = currentColor; // Top Left
+ vtxColorBufferPtr[j+1] = currentColor; // Top Right
+ vtxColorBufferPtr[j+2] = currentColor; // Bottom Right
+ vtxColorBufferPtr[j+3] = currentColor; // Bottom Left
}
}
diff --git a/desmume/src/frontend/cocoa/ClientDisplayView.h b/desmume/src/frontend/cocoa/ClientDisplayView.h
index 69b30fc05..d39f512e2 100644
--- a/desmume/src/frontend/cocoa/ClientDisplayView.h
+++ b/desmume/src/frontend/cocoa/ClientDisplayView.h
@@ -31,6 +31,7 @@
#define HUD_MAX_CHARACTERS 2048
#define HUD_VERTEX_ATTRIBUTE_BUFFER_SIZE (sizeof(float) * HUD_MAX_CHARACTERS * (2 * 4))
+#define HUD_VERTEX_COLOR_ATTRIBUTE_BUFFER_SIZE (sizeof(uint32_t) * HUD_MAX_CHARACTERS * 4)
#define HUD_TEXTBOX_BASEGLYPHSIZE 64.0
#define HUD_TEXTBOX_BASE_SCALE (1.0/3.0)
#define HUD_TEXTBOX_MIN_SCALE 0.70
@@ -160,6 +161,13 @@ protected:
bool _showCPULoadAverage;
bool _showRTC;
+ uint32_t _hudColorVideoFPS;
+ uint32_t _hudColorRender3DFPS;
+ uint32_t _hudColorFrameIndex;
+ uint32_t _hudColorLagFrameCount;
+ uint32_t _hudColorCPULoadAverage;
+ uint32_t _hudColorRTC;
+
ClientFrameInfo _clientFrameInfo;
NDSFrameInfo _ndsFrameInfo;
@@ -259,6 +267,18 @@ public:
virtual void SetHUDShowCPULoadAverage(const bool visibleState);
bool GetHUDShowRTC() const;
virtual void SetHUDShowRTC(const bool visibleState);
+ uint32_t GetHUDColorVideoFPS() const;
+ virtual void SetHUDColorVideoFPS(uint32_t color32);
+ uint32_t GetHUDColorRender3DFPS() const;
+ virtual void SetHUDColorRender3DFPS(uint32_t color32);
+ uint32_t GetHUDColorFrameIndex() const;
+ virtual void SetHUDColorFrameIndex(uint32_t color32);
+ uint32_t GetHUDColorLagFrameCount() const;
+ virtual void SetHUDColorLagFrameCount(uint32_t color32);
+ uint32_t GetHUDColorCPULoadAverage() const;
+ virtual void SetHUDColorCPULoadAverage(uint32_t color32);
+ uint32_t GetHUDColorRTC() const;
+ virtual void SetHUDColorRTC(uint32_t color32);
bool HUDNeedsUpdate();
void ClearHUDNeedsUpdate();
@@ -319,7 +339,8 @@ public:
virtual void SetSourceDeposterize(const bool useDeposterize);
- void SetHUDVertices(float viewportWidth, float viewportHeight, float *vtxBufferPtr);
+ void SetHUDPositionVertices(float viewportWidth, float viewportHeight, float *vtxPositionBufferPtr);
+ void SetHUDColorVertices(uint32_t *vtxColorBufferPtr);
void SetHUDTextureCoordinates(float *texCoordBufferPtr);
void SetScreenVertices(float *vtxBufferPtr);
void SetScreenTextureCoordinates(float w0, float h0, float w1, float h1, float *texCoordBufferPtr);
diff --git a/desmume/src/frontend/cocoa/DefaultUserPrefs.plist b/desmume/src/frontend/cocoa/DefaultUserPrefs.plist
index 28d97eb41..7c57c08ca 100644
--- a/desmume/src/frontend/cocoa/DefaultUserPrefs.plist
+++ b/desmume/src/frontend/cocoa/DefaultUserPrefs.plist
@@ -118,6 +118,18 @@
HUD_ShowRTC
+ HUD_Color_VideoFPS
+ 4294967295
+ HUD_Color_Render3DFPS
+ 4294967295
+ HUD_Color_FrameIndex
+ 4294967295
+ HUD_Color_LagFrameCount
+ 4294967295
+ HUD_Color_CPULoadAverage
+ 4294967295
+ HUD_Color_RTC
+ 4294967295
Input_AudioInputMode
1
Input_ControllerMappings
diff --git a/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp b/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp
index 1d4ff9765..37ee65be1 100644
--- a/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp
+++ b/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp
@@ -28,10 +28,12 @@
// VERTEX SHADER FOR HUD OUTPUT
static const char *HUDOutputVertShader_100 = {"\
ATTRIBUTE vec2 inPosition; \n\
+ ATTRIBUTE vec4 inColor; \n\
ATTRIBUTE vec2 inTexCoord0; \n\
\n\
uniform vec2 viewSize; \n\
\n\
+ VARYING vec4 vtxColor; \n\
VARYING vec2 texCoord[1]; \n\
\n\
void main() \n\
@@ -39,6 +41,7 @@ static const char *HUDOutputVertShader_100 = {"\
mat2 projection = mat2( vec2(2.0/viewSize.x, 0.0), \n\
vec2( 0.0, 2.0/viewSize.y)); \n\
\n\
+ vtxColor = inColor; \n\
texCoord[0] = inTexCoord0; \n\
gl_Position = vec4(projection * inPosition, 0.0, 1.0);\n\
} \n\
@@ -46,12 +49,13 @@ static const char *HUDOutputVertShader_100 = {"\
// FRAGMENT SHADER FOR HUD OUTPUT
static const char *HUDOutputFragShader_110 = {"\
+ VARYING vec4 vtxColor;\n\
VARYING vec2 texCoord[1];\n\
uniform sampler2D tex;\n\
\n\
void main()\n\
{\n\
- OUT_FRAG_COLOR = SAMPLE4_TEX_2D(tex, texCoord[0]);\n\
+ OUT_FRAG_COLOR = SAMPLE4_TEX_2D(tex, texCoord[0]) * vtxColor;\n\
}\n\
"};
@@ -4108,8 +4112,9 @@ static const char *Scaler6xBRZFragShader_110 = {"\
enum OGLVertexAttributeID
{
- OGLVertexAttributeID_Position = 0,
- OGLVertexAttributeID_TexCoord0 = 8
+ OGLVertexAttributeID_Position = 0,
+ OGLVertexAttributeID_TexCoord0 = 8,
+ OGLVertexAttributeID_Color = 3
};
static const GLint filterVtxBuffer[8] = {-1, -1, 1, -1, -1, 1, 1, 1};
@@ -4594,7 +4599,7 @@ GLuint OGLShaderProgram::GetVertexShaderID()
return this->_vertexID;
}
-void OGLShaderProgram::SetVertexShaderOGL(const char *shaderProgram, bool useShader150)
+void OGLShaderProgram::SetVertexShaderOGL(const char *shaderProgram, bool useVtxColors, bool useShader150)
{
if (this->_vertexID != 0)
{
@@ -4609,6 +4614,11 @@ void OGLShaderProgram::SetVertexShaderOGL(const char *shaderProgram, bool useSha
glAttachShader(this->_programID, this->_vertexID);
glBindAttribLocation(this->_programID, OGLVertexAttributeID_Position, "inPosition");
glBindAttribLocation(this->_programID, OGLVertexAttributeID_TexCoord0, "inTexCoord0");
+
+ if (useVtxColors)
+ {
+ glBindAttribLocation(this->_programID, OGLVertexAttributeID_Color, "inColor");
+ }
}
if (this->_vertexID != 0 && this->_fragmentID != 0)
@@ -4647,7 +4657,7 @@ void OGLShaderProgram::SetFragmentShaderOGL(const char *shaderProgram, bool useS
}
}
-void OGLShaderProgram::SetVertexAndFragmentShaderOGL(const char *vertShaderProgram, const char *fragShaderProgram, bool useShader150)
+void OGLShaderProgram::SetVertexAndFragmentShaderOGL(const char *vertShaderProgram, const char *fragShaderProgram, bool useVtxColors, bool useShader150)
{
if (this->_vertexID != 0)
{
@@ -4669,6 +4679,11 @@ void OGLShaderProgram::SetVertexAndFragmentShaderOGL(const char *vertShaderProgr
glAttachShader(this->_programID, this->_vertexID);
glBindAttribLocation(this->_programID, OGLVertexAttributeID_Position, "inPosition");
glBindAttribLocation(this->_programID, OGLVertexAttributeID_TexCoord0, "inTexCoord0");
+
+ if (useVtxColors)
+ {
+ glBindAttribLocation(this->_programID, OGLVertexAttributeID_Color, "inColor");
+ }
}
if (this->_fragmentID != 0)
@@ -5442,7 +5457,7 @@ OGLFilterDeposterize::OGLFilterDeposterize(GLsizei srcWidth, GLsizei srcHeight,
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
_program->SetShaderSupport(theTier);
- _program->SetVertexShaderOGL(Sample3x3_VertShader_110, useShader150);
+ _program->SetVertexShaderOGL(Sample3x3_VertShader_110, false, useShader150);
_program->SetFragmentShaderOGL(FilterDeposterizeFragShader_110, useShader150);
}
@@ -5595,7 +5610,7 @@ OGLImage::OGLImage(OGLContextInfo *contextInfo, GLsizei imageWidth, GLsizei imag
{
_finalOutputProgram = new OGLShaderProgram;
_finalOutputProgram->SetShaderSupport(_shaderSupport);
- _finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, _useShader150);
+ _finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, false, _useShader150);
const GLuint finalOutputProgramID = _finalOutputProgram->GetProgramID();
glUseProgram(finalOutputProgramID);
@@ -5617,7 +5632,7 @@ OGLImage::OGLImage(OGLContextInfo *contextInfo, GLsizei imageWidth, GLsizei imag
_shaderFilter = new OGLFilter(_vf->GetSrcWidth(), _vf->GetSrcHeight(), 1);
OGLShaderProgram *shaderFilterProgram = _shaderFilter->GetProgram();
shaderFilterProgram->SetShaderSupport(_shaderSupport);
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110, false, _useShader150);
SetupHQnxLUTs_OGL(GL_TEXTURE0 + 1, _texLQ2xLUT, _texHQ2xLUT, _texHQ3xLUT, _texHQ4xLUT);
}
@@ -5773,45 +5788,45 @@ void OGLImage::SetOutputFilterOGL(const int filterID)
switch (filterID)
{
case OutputFilterTypeID_NearestNeighbor:
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, _useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, false, _useShader150);
break;
case OutputFilterTypeID_Bilinear:
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, _useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, false, _useShader150);
this->_displayTexFilter = GL_LINEAR;
break;
case OutputFilterTypeID_BicubicBSpline:
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterBicubicBSplineFragShader_110, _useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterBicubicBSplineFragShader_110, false, _useShader150);
break;
case OutputFilterTypeID_BicubicMitchell:
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterBicubicMitchellNetravaliFragShader_110, _useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterBicubicMitchellNetravaliFragShader_110, false, _useShader150);
break;
case OutputFilterTypeID_Lanczos2:
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterLanczos2FragShader_110, _useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterLanczos2FragShader_110, false, _useShader150);
break;
case OutputFilterTypeID_Lanczos3:
{
if (this->_shaderSupport >= ShaderSupport_HighTier)
{
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample6x6Output_VertShader_110, FilterLanczos3FragShader_110, _useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample6x6Output_VertShader_110, FilterLanczos3FragShader_110, false, _useShader150);
}
else if (this->_shaderSupport >= ShaderSupport_MidTier)
{
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample5x5Output_VertShader_110, FilterLanczos3FragShader_110, _useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample5x5Output_VertShader_110, FilterLanczos3FragShader_110, false, _useShader150);
}
else
{
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterLanczos3FragShader_110, _useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterLanczos3FragShader_110, false, _useShader150);
}
break;
}
default:
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, _useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, false, _useShader150);
this->_outputFilter = OutputFilterTypeID_NearestNeighbor;
break;
}
@@ -5861,74 +5876,74 @@ bool OGLImage::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID)
switch (filterID)
{
case VideoFilterTypeID_Nearest1_5X:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110, false, _useShader150);
break;
case VideoFilterTypeID_Nearest2X:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110, false, _useShader150);
break;
case VideoFilterTypeID_Scanline:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, Scalar2xScanlineFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, Scalar2xScanlineFragShader_110, false, _useShader150);
break;
case VideoFilterTypeID_EPX:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, Scalar2xEPXFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, Scalar2xEPXFragShader_110, false, _useShader150);
break;
case VideoFilterTypeID_EPXPlus:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, Scalar2xEPXPlusFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, Scalar2xEPXPlusFragShader_110, false, _useShader150);
break;
case VideoFilterTypeID_2xSaI:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, Scalar2xSaIFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, Scalar2xSaIFragShader_110, false, _useShader150);
break;
case VideoFilterTypeID_Super2xSaI:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, ScalarSuper2xSaIFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, ScalarSuper2xSaIFragShader_110, false, _useShader150);
break;
case VideoFilterTypeID_SuperEagle:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, ScalarSuperEagle2xFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, ScalarSuperEagle2xFragShader_110, false, _useShader150);
break;
case VideoFilterTypeID_LQ2X:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerLQ2xFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerLQ2xFragShader_110, false, _useShader150);
currentHQnxLUT = this->_texLQ2xLUT;
break;
case VideoFilterTypeID_LQ2XS:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerLQ2xSFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerLQ2xSFragShader_110, false, _useShader150);
currentHQnxLUT = this->_texLQ2xLUT;
break;
case VideoFilterTypeID_HQ2X:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ2xFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ2xFragShader_110, false, _useShader150);
currentHQnxLUT = this->_texHQ2xLUT;
break;
case VideoFilterTypeID_HQ2XS:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ2xSFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ2xSFragShader_110, false, _useShader150);
currentHQnxLUT = this->_texHQ2xLUT;
break;
case VideoFilterTypeID_HQ3X:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ3xFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ3xFragShader_110, false, _useShader150);
currentHQnxLUT = this->_texHQ3xLUT;
break;
case VideoFilterTypeID_HQ3XS:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ3xSFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ3xSFragShader_110, false, _useShader150);
currentHQnxLUT = this->_texHQ3xLUT;
break;
case VideoFilterTypeID_HQ4X:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ4xFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ4xFragShader_110, false, _useShader150);
currentHQnxLUT = this->_texHQ4xLUT;
break;
case VideoFilterTypeID_HQ4XS:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ4xSFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ4xSFragShader_110, false, _useShader150);
currentHQnxLUT = this->_texHQ4xLUT;
break;
@@ -5936,11 +5951,11 @@ bool OGLImage::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID)
{
if (this->_shaderSupport >= ShaderSupport_MidTier)
{
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler2xBRZFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler2xBRZFragShader_110, false, _useShader150);
}
else if (this->_shaderSupport >= ShaderSupport_LowTier)
{
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, Scaler2xBRZFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, Scaler2xBRZFragShader_110, false, _useShader150);
}
else
{
@@ -5953,11 +5968,11 @@ bool OGLImage::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID)
{
if (this->_shaderSupport >= ShaderSupport_MidTier)
{
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler3xBRZFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler3xBRZFragShader_110, false, _useShader150);
}
else if (this->_shaderSupport >= ShaderSupport_LowTier)
{
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, Scaler3xBRZFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, Scaler3xBRZFragShader_110, false, _useShader150);
}
else
{
@@ -5970,7 +5985,7 @@ bool OGLImage::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID)
{
if (this->_shaderSupport >= ShaderSupport_MidTier)
{
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler4xBRZFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler4xBRZFragShader_110, false, _useShader150);
}
else
{
@@ -5984,7 +5999,7 @@ bool OGLImage::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID)
{
if (this->_shaderSupport >= ShaderSupport_MidTier)
{
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler5xBRZFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler5xBRZFragShader_110, false, _useShader150);
}
else
{
@@ -5997,7 +6012,7 @@ bool OGLImage::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID)
{
if (this->_shaderSupport >= ShaderSupport_MidTier)
{
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler6xBRZFragShader_110, _useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler6xBRZFragShader_110, false, _useShader150);
}
else
{
@@ -6187,7 +6202,7 @@ OGLHUDLayer::OGLHUDLayer(OGLVideoOutput *oglVO)
{
_program = new OGLShaderProgram;
_program->SetShaderSupport(oglVO->GetContextInfo()->GetShaderSupport());
- _program->SetVertexAndFragmentShaderOGL(HUDOutputVertShader_100, HUDOutputFragShader_110, oglVO->GetContextInfo()->IsUsingShader150());
+ _program->SetVertexAndFragmentShaderOGL(HUDOutputVertShader_100, HUDOutputFragShader_110, true, oglVO->GetContextInfo()->IsUsingShader150());
glUseProgram(_program->GetProgramID());
_uniformViewSize = glGetUniformLocation(_program->GetProgramID(), "viewSize");
@@ -6201,12 +6216,15 @@ OGLHUDLayer::OGLHUDLayer(OGLVideoOutput *oglVO)
glGenTextures(1, &_texCharMap);
// Set up VBOs
- glGenBuffersARB(1, &_vboVertexID);
+ glGenBuffersARB(1, &_vboPositionVertexID);
+ glGenBuffersARB(1, &_vboColorVertexID);
glGenBuffersARB(1, &_vboTexCoordID);
glGenBuffersARB(1, &_vboElementID);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboVertexID);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboPositionVertexID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, HUD_VERTEX_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW_ARB);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboColorVertexID);
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, HUD_VERTEX_COLOR_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboTexCoordID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, HUD_VERTEX_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
@@ -6234,24 +6252,30 @@ OGLHUDLayer::OGLHUDLayer(OGLVideoOutput *oglVO)
if (oglVO->GetContextInfo()->IsShaderSupported())
{
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboVertexID);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboPositionVertexID);
glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, NULL);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboColorVertexID);
+ glVertexAttribPointer(OGLVertexAttributeID_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboTexCoordID);
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, _vboElementID);
glEnableVertexAttribArray(OGLVertexAttributeID_Position);
+ glEnableVertexAttribArray(OGLVertexAttributeID_Color);
glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
}
else
{
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboVertexID);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboPositionVertexID);
glVertexPointer(2, GL_FLOAT, 0, NULL);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboColorVertexID);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, NULL);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboTexCoordID);
glTexCoordPointer(2, GL_FLOAT, 0, NULL);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, _vboElementID);
glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
@@ -6267,7 +6291,8 @@ OGLHUDLayer::~OGLHUDLayer()
}
glDeleteVertexArraysDESMUME(1, &this->_vaoMainStatesID);
- glDeleteBuffersARB(1, &this->_vboVertexID);
+ glDeleteBuffersARB(1, &this->_vboPositionVertexID);
+ glDeleteBuffersARB(1, &this->_vboColorVertexID);
glDeleteBuffersARB(1, &this->_vboTexCoordID);
glDeleteBuffersARB(1, &this->_vboElementID);
@@ -6310,7 +6335,7 @@ void OGLHUDLayer::CopyHUDFont(const FT_Face &fontFace, const size_t glyphSize, c
{
for (size_t pixIndex = 0; pixIndex < tileSize; pixIndex++)
{
- const uint32_t colorRGBA8888 = 0x50000000;
+ const uint32_t colorRGBA8888 = 0xFFFFFFFF;
charMapBuffer[(tileSize + pixIndex) + (rowIndex * (16 * tileSize))] = colorRGBA8888;
}
}
@@ -6368,10 +6393,16 @@ void OGLHUDLayer::_UpdateVerticesOGL()
return;
}
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboVertexID);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboPositionVertexID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, HUD_VERTEX_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW_ARB);
- float *vtxBufferPtr = (float *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- this->_output->SetHUDVertices((float)this->_output->GetViewportWidth(), (float)this->_output->GetViewportHeight(), vtxBufferPtr);
+ float *vtxPositionBufferPtr = (float *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ this->_output->SetHUDPositionVertices((float)this->_output->GetViewportWidth(), (float)this->_output->GetViewportHeight(), vtxPositionBufferPtr);
+ glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
+
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboColorVertexID);
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, HUD_VERTEX_COLOR_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW_ARB);
+ uint32_t *vtxColorBufferPtr = (uint32_t *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ this->_output->SetHUDColorVertices(vtxColorBufferPtr);
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboTexCoordID);
@@ -6496,7 +6527,7 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO)
{
_finalOutputProgram = new OGLShaderProgram;
_finalOutputProgram->SetShaderSupport(shaderSupport);
- _finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, useShader150);
+ _finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, false, useShader150);
const GLuint finalOutputProgramID = _finalOutputProgram->GetProgramID();
glUseProgram(finalOutputProgramID);
@@ -6519,7 +6550,7 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO)
_shaderFilter[i] = new OGLFilter(GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 1);
OGLShaderProgram *shaderFilterProgram = _shaderFilter[i]->GetProgram();
shaderFilterProgram->SetShaderSupport(shaderSupport);
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110, false, useShader150);
}
}
else
@@ -6614,46 +6645,46 @@ OutputFilterTypeID OGLDisplayLayer::SetOutputFilterOGL(const OutputFilterTypeID
switch (filterID)
{
case OutputFilterTypeID_NearestNeighbor:
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, false, useShader150);
break;
case OutputFilterTypeID_Bilinear:
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, false, useShader150);
this->_displayTexFilter[0] = GL_LINEAR;
this->_displayTexFilter[1] = GL_LINEAR;
break;
case OutputFilterTypeID_BicubicBSpline:
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterBicubicBSplineFragShader_110, useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterBicubicBSplineFragShader_110, false, useShader150);
break;
case OutputFilterTypeID_BicubicMitchell:
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterBicubicMitchellNetravaliFragShader_110, useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterBicubicMitchellNetravaliFragShader_110, false, useShader150);
break;
case OutputFilterTypeID_Lanczos2:
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterLanczos2FragShader_110, useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterLanczos2FragShader_110, false, useShader150);
break;
case OutputFilterTypeID_Lanczos3:
{
if (shaderSupport >= ShaderSupport_HighTier)
{
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample6x6Output_VertShader_110, FilterLanczos3FragShader_110, useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample6x6Output_VertShader_110, FilterLanczos3FragShader_110, false, useShader150);
}
else if (shaderSupport >= ShaderSupport_MidTier)
{
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample5x5Output_VertShader_110, FilterLanczos3FragShader_110, useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample5x5Output_VertShader_110, FilterLanczos3FragShader_110, false, useShader150);
}
else
{
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterLanczos3FragShader_110, useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(BicubicSample4x4Output_VertShader_110, FilterLanczos3FragShader_110, false, useShader150);
}
break;
}
default:
- this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, useShader150);
+ this->_finalOutputProgram->SetVertexAndFragmentShaderOGL(Sample1x1OutputVertShader_100, PassthroughOutputFragShader_110, false, useShader150);
outputFilter = OutputFilterTypeID_NearestNeighbor;
break;
}
@@ -6691,74 +6722,74 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID)
switch (filterID)
{
case VideoFilterTypeID_Nearest1_5X:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110, false, useShader150);
break;
case VideoFilterTypeID_Nearest2X:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110, false, useShader150);
break;
case VideoFilterTypeID_Scanline:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, Scalar2xScanlineFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, Scalar2xScanlineFragShader_110, false, useShader150);
break;
case VideoFilterTypeID_EPX:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, Scalar2xEPXFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, Scalar2xEPXFragShader_110, false, useShader150);
break;
case VideoFilterTypeID_EPXPlus:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, Scalar2xEPXPlusFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, Scalar2xEPXPlusFragShader_110, false, useShader150);
break;
case VideoFilterTypeID_2xSaI:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, Scalar2xSaIFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, Scalar2xSaIFragShader_110, false, useShader150);
break;
case VideoFilterTypeID_Super2xSaI:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, ScalarSuper2xSaIFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, ScalarSuper2xSaIFragShader_110, false, useShader150);
break;
case VideoFilterTypeID_SuperEagle:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, ScalarSuperEagle2xFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, ScalarSuperEagle2xFragShader_110, false, useShader150);
break;
case VideoFilterTypeID_LQ2X:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerLQ2xFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerLQ2xFragShader_110, false, useShader150);
currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexLQ2xLUT();
break;
case VideoFilterTypeID_LQ2XS:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerLQ2xSFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerLQ2xSFragShader_110, false, useShader150);
currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexLQ2xLUT();
break;
case VideoFilterTypeID_HQ2X:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ2xFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ2xFragShader_110, false, useShader150);
currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ2xLUT();
break;
case VideoFilterTypeID_HQ2XS:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ2xSFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ2xSFragShader_110, false, useShader150);
currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ2xLUT();
break;
case VideoFilterTypeID_HQ3X:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ3xFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ3xFragShader_110, false, useShader150);
currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ3xLUT();
break;
case VideoFilterTypeID_HQ3XS:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ3xSFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ3xSFragShader_110, false, useShader150);
currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ3xLUT();
break;
case VideoFilterTypeID_HQ4X:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ4xFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ4xFragShader_110, false, useShader150);
currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ4xLUT();
break;
case VideoFilterTypeID_HQ4XS:
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ4xSFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ4xSFragShader_110, false, useShader150);
currentHQnxLUT = ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ4xLUT();
break;
@@ -6766,11 +6797,11 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID)
{
if (shaderSupport >= ShaderSupport_MidTier)
{
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler2xBRZFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler2xBRZFragShader_110, false, useShader150);
}
else if (shaderSupport >= ShaderSupport_LowTier)
{
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, Scaler2xBRZFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, Scaler2xBRZFragShader_110, false, useShader150);
}
else
{
@@ -6783,11 +6814,11 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID)
{
if (shaderSupport >= ShaderSupport_MidTier)
{
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler3xBRZFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler3xBRZFragShader_110, false, useShader150);
}
else if (shaderSupport >= ShaderSupport_LowTier)
{
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, Scaler3xBRZFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample4x4_VertShader_110, Scaler3xBRZFragShader_110, false, useShader150);
}
else
{
@@ -6800,7 +6831,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID)
{
if (shaderSupport >= ShaderSupport_MidTier)
{
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler4xBRZFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler4xBRZFragShader_110, false, useShader150);
}
else
{
@@ -6813,7 +6844,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID)
{
if (shaderSupport >= ShaderSupport_MidTier)
{
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler5xBRZFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler5xBRZFragShader_110, false, useShader150);
}
else
{
@@ -6826,7 +6857,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID)
{
if (shaderSupport >= ShaderSupport_MidTier)
{
- shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler6xBRZFragShader_110, useShader150);
+ shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample5x5_VertShader_110, Scaler6xBRZFragShader_110, false, useShader150);
}
else
{
diff --git a/desmume/src/frontend/cocoa/OGLDisplayOutput.h b/desmume/src/frontend/cocoa/OGLDisplayOutput.h
index 291e60c55..22f3aae37 100644
--- a/desmume/src/frontend/cocoa/OGLDisplayOutput.h
+++ b/desmume/src/frontend/cocoa/OGLDisplayOutput.h
@@ -106,10 +106,10 @@ public:
ShaderSupportTier GetShaderSupport();
void SetShaderSupport(const ShaderSupportTier theTier);
GLuint GetVertexShaderID();
- void SetVertexShaderOGL(const char *shaderProgram, bool useShader150);
+ void SetVertexShaderOGL(const char *shaderProgram, bool useVtxColors, bool useShader150);
GLuint GetFragmentShaderID();
void SetFragmentShaderOGL(const char *shaderProgram, bool useShader150);
- void SetVertexAndFragmentShaderOGL(const char *vertShaderProgram, const char *fragShaderProgram, bool useShader150);
+ void SetVertexAndFragmentShaderOGL(const char *vertShaderProgram, const char *fragShaderProgram, bool useVtxColors, bool useShader150);
GLuint GetProgramID();
};
@@ -274,7 +274,8 @@ protected:
GLint _uniformViewSize;
GLuint _vaoMainStatesID;
- GLuint _vboVertexID;
+ GLuint _vboPositionVertexID;
+ GLuint _vboColorVertexID;
GLuint _vboTexCoordID;
GLuint _vboElementID;
GLuint _texCharMap;
diff --git a/desmume/src/frontend/cocoa/cocoa_output.h b/desmume/src/frontend/cocoa/cocoa_output.h
index 4a65b4d7a..d3b62b9fa 100644
--- a/desmume/src/frontend/cocoa/cocoa_output.h
+++ b/desmume/src/frontend/cocoa/cocoa_output.h
@@ -148,6 +148,12 @@
@property (assign) BOOL isHUDLagFrameCountVisible;
@property (assign) BOOL isHUDCPULoadAverageVisible;
@property (assign) BOOL isHUDRealTimeClockVisible;
+@property (assign) uint32_t hudColorVideoFPS;
+@property (assign) uint32_t hudColorRender3DFPS;
+@property (assign) uint32_t hudColorFrameIndex;
+@property (assign) uint32_t hudColorLagFrameCount;
+@property (assign) uint32_t hudColorCPULoadAverage;
+@property (assign) uint32_t hudColorRTC;
@property (assign) NSInteger displayMainVideoSource;
@property (assign) NSInteger displayTouchVideoSource;
@property (assign) BOOL useVerticalSync;
diff --git a/desmume/src/frontend/cocoa/cocoa_output.mm b/desmume/src/frontend/cocoa/cocoa_output.mm
index 648affa24..ae35efe6d 100644
--- a/desmume/src/frontend/cocoa/cocoa_output.mm
+++ b/desmume/src/frontend/cocoa/cocoa_output.mm
@@ -741,6 +741,12 @@
@dynamic isHUDLagFrameCountVisible;
@dynamic isHUDCPULoadAverageVisible;
@dynamic isHUDRealTimeClockVisible;
+@dynamic hudColorVideoFPS;
+@dynamic hudColorRender3DFPS;
+@dynamic hudColorFrameIndex;
+@dynamic hudColorLagFrameCount;
+@dynamic hudColorCPULoadAverage;
+@dynamic hudColorRTC;
@dynamic useVerticalSync;
@dynamic videoFiltersPreferGPU;
@dynamic sourceDeposterize;
@@ -895,6 +901,102 @@
return theState;
}
+- (void) setHudColorVideoFPS:(uint32_t)theColor
+{
+ OSSpinLockLock(&spinlockIsHUDVisible);
+ _cdv->SetHUDColorVideoFPS(theColor);
+ OSSpinLockUnlock(&spinlockIsHUDVisible);
+}
+
+- (uint32_t) hudColorVideoFPS
+{
+ OSSpinLockLock(&spinlockIsHUDVisible);
+ const uint32_t color32 = _cdv->GetHUDColorVideoFPS();
+ OSSpinLockUnlock(&spinlockIsHUDVisible);
+
+ return color32;
+}
+
+- (void) setHudColorRender3DFPS:(uint32_t)theColor
+{
+ OSSpinLockLock(&spinlockIsHUDVisible);
+ _cdv->SetHUDColorRender3DFPS(theColor);
+ OSSpinLockUnlock(&spinlockIsHUDVisible);
+}
+
+- (uint32_t) hudColorRender3DFPS
+{
+ OSSpinLockLock(&spinlockIsHUDVisible);
+ const uint32_t color32 = _cdv->GetHUDColorRender3DFPS();
+ OSSpinLockUnlock(&spinlockIsHUDVisible);
+
+ return color32;
+}
+
+- (void) setHudColorFrameIndex:(uint32_t)theColor
+{
+ OSSpinLockLock(&spinlockIsHUDVisible);
+ _cdv->SetHUDColorFrameIndex(theColor);
+ OSSpinLockUnlock(&spinlockIsHUDVisible);
+}
+
+- (uint32_t) hudColorFrameIndex
+{
+ OSSpinLockLock(&spinlockIsHUDVisible);
+ const uint32_t color32 = _cdv->GetHUDColorFrameIndex();
+ OSSpinLockUnlock(&spinlockIsHUDVisible);
+
+ return color32;
+}
+
+- (void) setHudColorLagFrameCount:(uint32_t)theColor
+{
+ OSSpinLockLock(&spinlockIsHUDVisible);
+ _cdv->SetHUDColorLagFrameCount(theColor);
+ OSSpinLockUnlock(&spinlockIsHUDVisible);
+}
+
+- (uint32_t) hudColorLagFrameCount
+{
+ OSSpinLockLock(&spinlockIsHUDVisible);
+ const uint32_t color32 = _cdv->GetHUDColorLagFrameCount();
+ OSSpinLockUnlock(&spinlockIsHUDVisible);
+
+ return color32;
+}
+
+- (void) setHudColorCPULoadAverage:(uint32_t)theColor
+{
+ OSSpinLockLock(&spinlockIsHUDVisible);
+ _cdv->SetHUDColorCPULoadAverage(theColor);
+ OSSpinLockUnlock(&spinlockIsHUDVisible);
+}
+
+- (uint32_t) hudColorCPULoadAverage
+{
+ OSSpinLockLock(&spinlockIsHUDVisible);
+ const uint32_t color32 = _cdv->GetHUDColorCPULoadAverage();
+ OSSpinLockUnlock(&spinlockIsHUDVisible);
+
+ return color32;
+}
+
+- (void) setHudColorRTC:(uint32_t)theColor
+{
+ OSSpinLockLock(&spinlockIsHUDVisible);
+ _cdv->SetHUDColorRTC(theColor);
+ OSSpinLockUnlock(&spinlockIsHUDVisible);
+}
+
+- (uint32_t) hudColorRTC
+{
+ OSSpinLockLock(&spinlockIsHUDVisible);
+ const uint32_t color32 = _cdv->GetHUDColorRTC();
+ OSSpinLockUnlock(&spinlockIsHUDVisible);
+
+ return color32;
+}
+
- (void) setDisplayMainVideoSource:(NSInteger)displaySourceID
{
OSSpinLockLock(&spinlockDisplayVideoSource);
diff --git a/desmume/src/frontend/cocoa/cocoa_util.h b/desmume/src/frontend/cocoa/cocoa_util.h
index fe8eb3f97..de750d225 100644
--- a/desmume/src/frontend/cocoa/cocoa_util.h
+++ b/desmume/src/frontend/cocoa/cocoa_util.h
@@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
- Copyright (C) 2012-2013 DeSmuME team
+ Copyright (C) 2012-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,6 +17,7 @@
*/
#import
+#import
#include
#include "utilities.h"
@@ -40,6 +41,9 @@
+ (NSInteger) getIBActionSenderTag:(id)sender;
+ (BOOL) getIBActionSenderButtonStateBool:(id)sender;
++ (NSColor *) NSColorFromRGBA8888:(uint32_t)theColor;
++ (uint32_t) RGBA8888FromNSColor:(NSColor *)theColor;
+
+ (NSInteger) appVersionNumeric;
+ (NSString *) appInternalVersionString;
+ (NSString *) appInternalNameAndVersionString;
@@ -90,3 +94,8 @@
- (void)postNotificationOnMainThreadName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
@end
+
+@interface RGBA8888ToNSColorValueTransformer : NSValueTransformer
+{ }
+@end
+
diff --git a/desmume/src/frontend/cocoa/cocoa_util.mm b/desmume/src/frontend/cocoa/cocoa_util.mm
index a65537311..ece192fd0 100644
--- a/desmume/src/frontend/cocoa/cocoa_util.mm
+++ b/desmume/src/frontend/cocoa/cocoa_util.mm
@@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
- Copyright (C) 2012-2016 DeSmuME team
+ Copyright (C) 2012-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -156,6 +156,36 @@ static NSDate *distantFutureDate = [[NSDate distantFuture] retain];
return theState;
}
++ (NSColor *) NSColorFromRGBA8888:(uint32_t)theColor
+{
+ const CGFloat r = (CGFloat)((theColor >> 0) & 0xFF) / 255.0f;
+ const CGFloat g = (CGFloat)((theColor >> 8) & 0xFF) / 255.0f;
+ const CGFloat b = (CGFloat)((theColor >> 16) & 0xFF) / 255.0f;
+ const CGFloat a = (CGFloat)((theColor >> 24) & 0xFF) / 255.0f;
+
+ return [NSColor colorWithDeviceRed:r green:g blue:b alpha:a];
+}
+
++ (uint32_t) RGBA8888FromNSColor:(NSColor *)theColor
+{
+ if (![[theColor colorSpaceName] isEqualToString:NSDeviceRGBColorSpace])
+ {
+ theColor = [theColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ if (theColor == nil)
+ {
+ return 0x00000000;
+ }
+ }
+
+ CGFloat r, g, b, a;
+ [theColor getRed:&r green:&g blue:&b alpha:&a];
+
+ return (((uint32_t)(r * 255.0f)) << 0) |
+ (((uint32_t)(g * 255.0f)) << 8) |
+ (((uint32_t)(b * 255.0f)) << 16) |
+ (((uint32_t)(a * 255.0f)) << 24);
+}
+
+ (NSInteger) appVersionNumeric
{
return (NSInteger)EMU_DESMUME_VERSION_NUMERIC();
@@ -352,3 +382,68 @@ static NSDate *distantFutureDate = [[NSDate distantFuture] retain];
}
@end
+
+@implementation RGBA8888ToNSColorValueTransformer
+
++ (Class)transformedValueClass
+{
+ return [NSColor class];
+}
+
++ (BOOL)allowsReverseTransformation
+{
+ return YES;
+}
+
+- (id)transformedValue:(id)value
+{
+ if (value == nil)
+ {
+ return nil;
+ }
+
+ uint32_t color32 = 0xFFFFFFFF;
+
+ if ([value respondsToSelector:@selector(unsignedIntegerValue)])
+ {
+ color32 = (uint32_t)[value unsignedIntegerValue];
+ }
+ else if ([value respondsToSelector:@selector(unsignedIntValue)])
+ {
+ color32 = (uint32_t)[value unsignedIntValue];
+ }
+ else if ([value respondsToSelector:@selector(integerValue)])
+ {
+ color32 = (uint32_t)[value integerValue];
+ }
+ else if ([value respondsToSelector:@selector(intValue)])
+ {
+ color32 = (uint32_t)[value intValue];
+ }
+ else
+ {
+ [NSException raise:NSInternalInconsistencyException format:@"Value (%@) does not respond to -unsignedIntegerValue, -unsignedIntValue, -integerValue or -intValue.", [value class]];
+ }
+
+ return [CocoaDSUtil NSColorFromRGBA8888:color32];
+}
+
+- (id)reverseTransformedValue:(id)value
+{
+ uint32_t color32 = 0xFFFFFFFF;
+
+ if (value == nil)
+ {
+ return nil;
+ }
+ else if (![value isKindOfClass:[NSColor class]])
+ {
+ NSLog(@"-reverseTransformedValue is %@", [value class]);
+ return [NSNumber numberWithUnsignedInteger:color32];
+ }
+
+ color32 = [CocoaDSUtil RGBA8888FromNSColor:(NSColor *)value];
+ return [NSNumber numberWithUnsignedInteger:color32];
+}
+
+@end
diff --git a/desmume/src/frontend/cocoa/translations/English.lproj/MainMenu.strings b/desmume/src/frontend/cocoa/translations/English.lproj/MainMenu.strings
index cceb76865..beb7a1bc9 100644
Binary files a/desmume/src/frontend/cocoa/translations/English.lproj/MainMenu.strings and b/desmume/src/frontend/cocoa/translations/English.lproj/MainMenu.strings differ
diff --git a/desmume/src/frontend/cocoa/translations/English.lproj/MainMenu.xib b/desmume/src/frontend/cocoa/translations/English.lproj/MainMenu.xib
index 736b5e959..4c0d72557 100644
--- a/desmume/src/frontend/cocoa/translations/English.lproj/MainMenu.xib
+++ b/desmume/src/frontend/cocoa/translations/English.lproj/MainMenu.xib
@@ -12,7 +12,6 @@