mirror of https://github.com/stella-emu/stella.git
Removed all traces of the OpenGL TV filters. This is due to be replaced by
Blargg NTSC filtering, but we need to revert to base functionality first. Cleaned up the debugger API wrt converting values from integers to strings (and vice-versa). There is now only one method for each of these functions, rather than several ways to do so. In the process, convert from unsafe sprintf functions into snprintf (eliminate potential buffer overflows). The debugger 'print' command now indicates if any assigned label represents a read-only location (R), a write-only location (W), or a read/write location (R/W). Fixed bug in DataGridWidgets (used in debugger ROM and CPU registers), where scrolling the mouse-wheel would cause a segfault. Scrolling the mousewheel now changes these items as expected. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2260 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
221aa50a5b
commit
377765f565
13
Changes.txt
13
Changes.txt
|
@ -12,6 +12,17 @@
|
||||||
Release History
|
Release History
|
||||||
===========================================================================
|
===========================================================================
|
||||||
|
|
||||||
|
3.4.1 to 4.x: (XXXX xx, 2011)
|
||||||
|
|
||||||
|
* The debugger 'print' command now indicates "special" addresses if they
|
||||||
|
are read-only (R), write-only (W) or read-write (R/W).
|
||||||
|
|
||||||
|
* Fixed a bug in scrolling the mouse-wheel in certain debugger UI items
|
||||||
|
would cause the program to crash; scrolling now works as expected.
|
||||||
|
|
||||||
|
-Have fun!
|
||||||
|
|
||||||
|
|
||||||
3.4 to 3.4.1: (June 11, 2011)
|
3.4 to 3.4.1: (June 11, 2011)
|
||||||
|
|
||||||
* Re-enabled 'grabmouse' commandline argument and associated
|
* Re-enabled 'grabmouse' commandline argument and associated
|
||||||
|
@ -47,8 +58,6 @@
|
||||||
* Zero-byte ROMs are no longer loaded and mis-detected as Supercharger
|
* Zero-byte ROMs are no longer loaded and mis-detected as Supercharger
|
||||||
images.
|
images.
|
||||||
|
|
||||||
-Have fun!
|
|
||||||
|
|
||||||
|
|
||||||
3.3 to 3.4: (May. 29, 2011)
|
3.3 to 3.4: (May. 29, 2011)
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#include "OSystem.hxx"
|
#include "OSystem.hxx"
|
||||||
#include "Settings.hxx"
|
#include "Settings.hxx"
|
||||||
#include "TIA.hxx"
|
#include "TIA.hxx"
|
||||||
#include "GLShaderProgs.hxx"
|
|
||||||
|
|
||||||
#include "FrameBufferGL.hxx"
|
#include "FrameBufferGL.hxx"
|
||||||
|
|
||||||
|
@ -264,28 +263,6 @@ bool FrameBufferGL::setVidMode(VideoMode& mode)
|
||||||
uInt32 baseWidth = mode.image_w / mode.gfxmode.zoom;
|
uInt32 baseWidth = mode.image_w / mode.gfxmode.zoom;
|
||||||
uInt32 baseHeight = mode.image_h / mode.gfxmode.zoom;
|
uInt32 baseHeight = mode.image_h / mode.gfxmode.zoom;
|
||||||
|
|
||||||
// Update the graphics filter options
|
|
||||||
myUseTexture = true; myTextureStag = false;
|
|
||||||
const string& tv_tex = myOSystem->settings().getString("tv_tex");
|
|
||||||
if(tv_tex == "stag") myTextureStag = true;
|
|
||||||
else if(tv_tex != "normal") myUseTexture = false;
|
|
||||||
|
|
||||||
myUseBleed = true;
|
|
||||||
const string& tv_bleed = myOSystem->settings().getString("tv_bleed");
|
|
||||||
if(tv_bleed == "low") myBleedQuality = 0;
|
|
||||||
else if(tv_bleed == "medium") myBleedQuality = 1;
|
|
||||||
else if(tv_bleed == "high") myBleedQuality = 2;
|
|
||||||
else myUseBleed = false;
|
|
||||||
|
|
||||||
myUseNoise = true;
|
|
||||||
const string& tv_noise = myOSystem->settings().getString("tv_noise");
|
|
||||||
if(tv_noise == "low") myNoiseQuality = 5;
|
|
||||||
else if(tv_noise == "medium") myNoiseQuality = 15;
|
|
||||||
else if(tv_noise == "high") myNoiseQuality = 25;
|
|
||||||
else myUseNoise = false;
|
|
||||||
|
|
||||||
myUseGLPhosphor = myOSystem->settings().getBool("tv_phos");
|
|
||||||
|
|
||||||
// Set the zoom level
|
// Set the zoom level
|
||||||
myZoomLevel = mode.gfxmode.zoom;
|
myZoomLevel = mode.gfxmode.zoom;
|
||||||
|
|
||||||
|
@ -577,23 +554,10 @@ FBSurfaceGL::FBSurfaceGL(FrameBufferGL& buffer,
|
||||||
: myFB(buffer),
|
: myFB(buffer),
|
||||||
myTexture(NULL),
|
myTexture(NULL),
|
||||||
myTexID(0),
|
myTexID(0),
|
||||||
myFilterTexID(0),
|
|
||||||
mySubMaskTexID(0),
|
|
||||||
myNoiseMaskTexID(NULL),
|
|
||||||
myPhosphorTexID(0),
|
|
||||||
mySubpixelTexture(NULL),
|
|
||||||
myNoiseTexture(NULL),
|
|
||||||
myXOrig(0),
|
myXOrig(0),
|
||||||
myYOrig(0),
|
myYOrig(0),
|
||||||
myWidth(scaleWidth),
|
myWidth(scaleWidth),
|
||||||
myHeight(scaleHeight),
|
myHeight(scaleHeight)
|
||||||
myBleedProgram(0),
|
|
||||||
myTextureProgram(0),
|
|
||||||
myNoiseProgram(0),
|
|
||||||
myPhosphorProgram(0),
|
|
||||||
myTextureNoiseProgram(0),
|
|
||||||
myNoiseNum(0),
|
|
||||||
myTvFiltersEnabled(false)
|
|
||||||
{
|
{
|
||||||
// Fill buffer struct with valid data
|
// Fill buffer struct with valid data
|
||||||
// This changes depending on the texturing used
|
// This changes depending on the texturing used
|
||||||
|
@ -606,9 +570,6 @@ FBSurfaceGL::FBSurfaceGL(FrameBufferGL& buffer,
|
||||||
myTexTarget = GL_TEXTURE_RECTANGLE_ARB;
|
myTexTarget = GL_TEXTURE_RECTANGLE_ARB;
|
||||||
myTexCoord[2] = (GLfloat) myTexWidth;
|
myTexCoord[2] = (GLfloat) myTexWidth;
|
||||||
myTexCoord[3] = (GLfloat) myTexHeight;
|
myTexCoord[3] = (GLfloat) myTexHeight;
|
||||||
|
|
||||||
// This is a quick fix, a better one will come later
|
|
||||||
myTvFiltersEnabled = false;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -626,218 +587,6 @@ FBSurfaceGL::FBSurfaceGL(FrameBufferGL& buffer,
|
||||||
0x00007c00, 0x000003e0, 0x0000001f, 0x00000000);
|
0x00007c00, 0x000003e0, 0x0000001f, 0x00000000);
|
||||||
myPitch = myTexture->pitch >> 1;
|
myPitch = myTexture->pitch >> 1;
|
||||||
|
|
||||||
// The 'allowFiltering' boolean is only a hint that filtering is allowed
|
|
||||||
// on this surface
|
|
||||||
// We still need to check if the functionality exists to do it
|
|
||||||
if(allowFiltering)
|
|
||||||
{
|
|
||||||
// It's only enabled if we use one of the filters *AND* GLSL is available
|
|
||||||
myTvFiltersEnabled = myFB.myGLSLAvailable &&
|
|
||||||
(myFB.myUseTexture || myFB.myUseNoise ||
|
|
||||||
myFB.myUseBleed || myFB.myUseGLPhosphor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
myTvFiltersEnabled = false;
|
|
||||||
|
|
||||||
// Only do this if TV filters enabled, otherwise it won't be used anyway
|
|
||||||
if(myTvFiltersEnabled)
|
|
||||||
{
|
|
||||||
// For a reason that hasn't been investigated yet, some of the filter and mask
|
|
||||||
// texture coordinates need to be swapped in order for it not to render upside down
|
|
||||||
|
|
||||||
myFilterTexCoord[0] = 0.0f;
|
|
||||||
myFilterTexCoord[3] = 0.0f;
|
|
||||||
|
|
||||||
if(myFB.myHaveTexRectEXT)
|
|
||||||
{
|
|
||||||
myFilterTexWidth = scaleWidth;
|
|
||||||
myFilterTexHeight = scaleHeight;
|
|
||||||
myFilterTexCoord[2] = (GLfloat) myFilterTexWidth;
|
|
||||||
myFilterTexCoord[1] = (GLfloat) myFilterTexHeight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
myFilterTexWidth = power_of_two(scaleWidth);
|
|
||||||
myFilterTexHeight = power_of_two(scaleHeight);
|
|
||||||
myFilterTexCoord[2] = (GLfloat) scaleWidth / myFilterTexWidth;
|
|
||||||
myFilterTexCoord[1] = (GLfloat) scaleHeight / myFilterTexHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only do this if TV and color bleed filters are enabled
|
|
||||||
// This filer applies a color averaging of surrounding pixels for each pixel
|
|
||||||
if(myFB.myUseBleed)
|
|
||||||
{
|
|
||||||
// Load shader programs. If it fails, don't use this filter.
|
|
||||||
myBleedProgram = genShader(SHADER_BLEED);
|
|
||||||
if(myBleedProgram == 0)
|
|
||||||
{
|
|
||||||
myFB.myUseBleed = false;
|
|
||||||
cout << "ERROR: Failed to make bleed programs" << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the texture and noise filters are enabled together, we can use a single shader
|
|
||||||
// Make sure we can use three textures at once first
|
|
||||||
GLint texUnits;
|
|
||||||
p_glGetIntegerv(GL_MAX_TEXTURE_UNITS, &texUnits);
|
|
||||||
if(texUnits >= 3 && myFB.myUseTexture && myFB.myUseNoise)
|
|
||||||
{
|
|
||||||
// Load shader program. If it fails, don't use this shader.
|
|
||||||
myTextureNoiseProgram = genShader(SHADER_TEXNOISE);
|
|
||||||
if(myTextureNoiseProgram == 0)
|
|
||||||
{
|
|
||||||
cout << "ERROR: Failed to make texture/noise program" << endl;
|
|
||||||
|
|
||||||
// Load shader program. If it fails, don't use this filter.
|
|
||||||
myTextureProgram = genShader(SHADER_TEX);
|
|
||||||
if(myTextureProgram == 0)
|
|
||||||
{
|
|
||||||
myFB.myUseTexture = false;
|
|
||||||
cout << "ERROR: Failed to make texture program" << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load shader program. If it fails, don't use this filter.
|
|
||||||
myNoiseProgram = genShader(SHADER_NOISE);
|
|
||||||
if(myNoiseProgram == 0)
|
|
||||||
{
|
|
||||||
myFB.myUseNoise = false;
|
|
||||||
cout << "ERROR: Failed to make noise program" << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Else, detect individual settings
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(myFB.myUseTexture)
|
|
||||||
{
|
|
||||||
// Load shader program. If it fails, don't use this filter.
|
|
||||||
myTextureProgram = genShader(SHADER_TEX);
|
|
||||||
if(myTextureProgram == 0)
|
|
||||||
{
|
|
||||||
myFB.myUseTexture = false;
|
|
||||||
cout << "ERROR: Failed to make texture program" << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(myFB.myUseNoise)
|
|
||||||
{
|
|
||||||
// Load shader program. If it fails, don't use this filter.
|
|
||||||
myNoiseProgram = genShader(SHADER_NOISE);
|
|
||||||
if(myNoiseProgram == 0)
|
|
||||||
{
|
|
||||||
myFB.myUseNoise = false;
|
|
||||||
cout << "ERROR: Failed to make noise program" << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only do this if TV and color texture filters are enabled
|
|
||||||
// This filter applies an RGB color pixel mask as well as a blackspace mask
|
|
||||||
if(myFB.myUseTexture)
|
|
||||||
{
|
|
||||||
// Prepare subpixel texture
|
|
||||||
mySubpixelTexture = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
|
||||||
myFilterTexWidth, myFilterTexHeight, 16,
|
|
||||||
0x00007c00, 0x000003e0, 0x0000001f, 0x00000000);
|
|
||||||
|
|
||||||
uInt32 pCounter = 0;
|
|
||||||
for (uInt32 y = 0; y < (uInt32)myFilterTexHeight; y++)
|
|
||||||
{
|
|
||||||
for (uInt32 x = 0; x < (uInt32)myFilterTexWidth; x++)
|
|
||||||
{
|
|
||||||
// Cause vertical offset for every other black row if enabled
|
|
||||||
uInt32 offsetY;
|
|
||||||
if (!myFB.myTextureStag || x % 6 < 3)
|
|
||||||
offsetY = y;
|
|
||||||
else
|
|
||||||
offsetY = y + 2;
|
|
||||||
|
|
||||||
// Make a row of black for the mask every so often
|
|
||||||
if (offsetY % 4 == 0)
|
|
||||||
{
|
|
||||||
((uInt16*)mySubpixelTexture->pixels)[pCounter] = 0x0000;
|
|
||||||
}
|
|
||||||
// Apply the coorect color mask
|
|
||||||
else
|
|
||||||
{
|
|
||||||
((uInt16*)mySubpixelTexture->pixels)[pCounter] = 0x7c00 >> ((x % 3) * 5);
|
|
||||||
}
|
|
||||||
pCounter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only do this if TV and noise filters are enabled
|
|
||||||
// This filter applies a texture filled with gray pixel of random intensities
|
|
||||||
if(myFB.myUseNoise)
|
|
||||||
{
|
|
||||||
// Get the current number of nose textures to use
|
|
||||||
myNoiseNum = myFB.myNoiseQuality;
|
|
||||||
|
|
||||||
// Allocate space for noise textures
|
|
||||||
myNoiseTexture = new SDL_Surface*[myNoiseNum];
|
|
||||||
myNoiseMaskTexID = new GLuint[myNoiseNum];
|
|
||||||
|
|
||||||
// Prepare noise textures
|
|
||||||
for(int i = 0; i < myNoiseNum; i++)
|
|
||||||
{
|
|
||||||
myNoiseTexture[i] = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
|
||||||
myFilterTexWidth, myFilterTexHeight, 16,
|
|
||||||
0x00007c00, 0x000003e0, 0x0000001f, 0x00000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
uInt32 pCounter = 0;
|
|
||||||
for(int i = 0; i < myNoiseNum; i++)
|
|
||||||
{
|
|
||||||
pCounter = 0;
|
|
||||||
|
|
||||||
// Attempt to make the numbers as random as possible
|
|
||||||
int temp = (unsigned)time(0) + rand()/4;
|
|
||||||
srand(temp);
|
|
||||||
|
|
||||||
for (uInt32 y = 0; y < (uInt32)myFilterTexHeight; y++)
|
|
||||||
{
|
|
||||||
for (uInt32 x = 0; x < (uInt32)myFilterTexWidth; x++)
|
|
||||||
{
|
|
||||||
// choose random 0 - 2
|
|
||||||
// 0 = 0x0000
|
|
||||||
// 1 = 0x0421
|
|
||||||
// 2 = 0x0842
|
|
||||||
int num = rand() % 3;
|
|
||||||
if (num == 0)
|
|
||||||
((uInt16*)myNoiseTexture[i]->pixels)[pCounter] = 0x0000;
|
|
||||||
else if (num == 1)
|
|
||||||
((uInt16*)myNoiseTexture[i]->pixels)[pCounter] = 0x0421;
|
|
||||||
else if (num == 2)
|
|
||||||
((uInt16*)myNoiseTexture[i]->pixels)[pCounter] = 0x0842;
|
|
||||||
|
|
||||||
pCounter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only do this if TV and phosphor filters are enabled
|
|
||||||
// This filter merges the past screen with the current one, to give a phosphor burn-off effect
|
|
||||||
if(myFB.myUseGLPhosphor)
|
|
||||||
{
|
|
||||||
// Load shader program. If it fails, don't use this filter.
|
|
||||||
myPhosphorProgram = genShader(SHADER_PHOS);
|
|
||||||
if(myPhosphorProgram == 0)
|
|
||||||
{
|
|
||||||
myFB.myUseGLPhosphor = false;
|
|
||||||
cout << "ERROR: Failed to make phosphor program" << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check to see if filters should still be used
|
|
||||||
// Filtering must have been previously enabled, and GLSL must still be
|
|
||||||
// available
|
|
||||||
myTvFiltersEnabled = myTvFiltersEnabled && myFB.myGLSLAvailable &&
|
|
||||||
(myFB.myUseTexture || myFB.myUseNoise ||
|
|
||||||
myFB.myUseBleed || myFB.myUseGLPhosphor);
|
|
||||||
|
|
||||||
// Associate the SDL surface with a GL texture object
|
// Associate the SDL surface with a GL texture object
|
||||||
reload();
|
reload();
|
||||||
}
|
}
|
||||||
|
@ -848,13 +597,6 @@ FBSurfaceGL::~FBSurfaceGL()
|
||||||
if(myTexture)
|
if(myTexture)
|
||||||
SDL_FreeSurface(myTexture);
|
SDL_FreeSurface(myTexture);
|
||||||
|
|
||||||
if(mySubpixelTexture)
|
|
||||||
SDL_FreeSurface(mySubpixelTexture);
|
|
||||||
|
|
||||||
if(myNoiseTexture)
|
|
||||||
for(int i = 0; i < myNoiseNum; i++)
|
|
||||||
SDL_FreeSurface(myNoiseTexture[i]);
|
|
||||||
|
|
||||||
free();
|
free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1043,198 +785,27 @@ void FBSurfaceGL::update()
|
||||||
{
|
{
|
||||||
if(mySurfaceIsDirty)
|
if(mySurfaceIsDirty)
|
||||||
{
|
{
|
||||||
GLint loc;
|
// Texturemap complete texture to surface so we have free scaling
|
||||||
|
// and antialiasing
|
||||||
|
p_glActiveTexture(GL_TEXTURE0);
|
||||||
|
p_glBindTexture(myTexTarget, myTexID);
|
||||||
|
p_glTexSubImage2D(myTexTarget, 0, 0, 0, myTexWidth, myTexHeight,
|
||||||
|
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, myTexture->pixels);
|
||||||
|
|
||||||
// Set a boolean to tell which filter is a first render (if any are applied).
|
// Pass in texture as a variable
|
||||||
// Being a first render means using the Atari frame buffer instead of the
|
p_glBegin(GL_QUADS);
|
||||||
// previous rendered data.
|
p_glTexCoord2f(myTexCoord[0], myTexCoord[1]);
|
||||||
bool firstRender = true;
|
p_glVertex2i(myXOrig, myYOrig);
|
||||||
|
|
||||||
// Render as usual if no filters are used
|
p_glTexCoord2f(myTexCoord[2], myTexCoord[1]);
|
||||||
if(!myTvFiltersEnabled)
|
p_glVertex2i(myXOrig + myWidth, myYOrig);
|
||||||
{
|
|
||||||
// Texturemap complete texture to surface so we have free scaling
|
|
||||||
// and antialiasing
|
|
||||||
p_glActiveTexture(GL_TEXTURE0);
|
|
||||||
p_glBindTexture(myTexTarget, myTexID);
|
|
||||||
p_glTexSubImage2D(myTexTarget, 0, 0, 0, myTexWidth, myTexHeight,
|
|
||||||
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, myTexture->pixels);
|
|
||||||
|
|
||||||
// Pass in texture as a variable
|
p_glTexCoord2f(myTexCoord[2], myTexCoord[3]);
|
||||||
p_glBegin(GL_QUADS);
|
p_glVertex2i(myXOrig + myWidth, myYOrig + myHeight);
|
||||||
p_glTexCoord2f(myTexCoord[0], myTexCoord[1]);
|
|
||||||
p_glVertex2i(myXOrig, myYOrig);
|
|
||||||
|
|
||||||
p_glTexCoord2f(myTexCoord[2], myTexCoord[1]);
|
p_glTexCoord2f(myTexCoord[0], myTexCoord[3]);
|
||||||
p_glVertex2i(myXOrig + myWidth, myYOrig);
|
p_glVertex2i(myXOrig, myYOrig + myHeight);
|
||||||
|
p_glEnd();
|
||||||
p_glTexCoord2f(myTexCoord[2], myTexCoord[3]);
|
|
||||||
p_glVertex2i(myXOrig + myWidth, myYOrig + myHeight);
|
|
||||||
|
|
||||||
p_glTexCoord2f(myTexCoord[0], myTexCoord[3]);
|
|
||||||
p_glVertex2i(myXOrig, myYOrig + myHeight);
|
|
||||||
p_glEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If TV filters are enabled
|
|
||||||
// TODO - check if this IF is necessary, or can it be chained by else to above
|
|
||||||
if(myTvFiltersEnabled)
|
|
||||||
{
|
|
||||||
// If combined texture/noise program exists,
|
|
||||||
// use the combined one; else do them separately
|
|
||||||
if(myTextureNoiseProgram != 0)
|
|
||||||
{
|
|
||||||
p_glUseProgram(myTextureNoiseProgram);
|
|
||||||
|
|
||||||
// Pass in subpixel mask texture
|
|
||||||
p_glActiveTexture(GL_TEXTURE1);
|
|
||||||
p_glBindTexture(myTexTarget, mySubMaskTexID);
|
|
||||||
loc = p_glGetUniformLocation(myTextureNoiseProgram, "texMask");
|
|
||||||
p_glUniform1i(loc, 1);
|
|
||||||
|
|
||||||
// Choose random mask texture
|
|
||||||
int num = rand() % myNoiseNum;
|
|
||||||
// Pass in noise mask texture
|
|
||||||
p_glActiveTexture(GL_TEXTURE2);
|
|
||||||
p_glBindTexture(myTexTarget, myNoiseMaskTexID[num]);
|
|
||||||
loc = p_glGetUniformLocation(myTextureNoiseProgram, "noiseMask");
|
|
||||||
p_glUniform1i(loc, 2);
|
|
||||||
|
|
||||||
renderThreeTexture(myTextureNoiseProgram, firstRender);
|
|
||||||
|
|
||||||
// We have rendered, set firstRender to false
|
|
||||||
firstRender = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Check if texture filter is enabled
|
|
||||||
if(myFB.myUseTexture)
|
|
||||||
{
|
|
||||||
p_glUseProgram(myTextureProgram);
|
|
||||||
|
|
||||||
// Pass in subpixel mask texture
|
|
||||||
p_glActiveTexture(GL_TEXTURE1);
|
|
||||||
p_glBindTexture(myTexTarget, mySubMaskTexID);
|
|
||||||
loc = p_glGetUniformLocation(myTextureProgram, "mask");
|
|
||||||
p_glUniform1i(loc, 1);
|
|
||||||
|
|
||||||
renderTwoTexture(myTextureProgram, firstRender);
|
|
||||||
|
|
||||||
// We have rendered, set firstRender to false
|
|
||||||
firstRender = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(myFB.myUseNoise)
|
|
||||||
{
|
|
||||||
p_glUseProgram(myNoiseProgram);
|
|
||||||
|
|
||||||
// Choose random mask texture
|
|
||||||
int num = rand() % myNoiseNum;
|
|
||||||
|
|
||||||
// Pass in noise mask texture
|
|
||||||
p_glActiveTexture(GL_TEXTURE1);
|
|
||||||
p_glBindTexture(myTexTarget, myNoiseMaskTexID[num]);
|
|
||||||
loc = p_glGetUniformLocation(myNoiseProgram, "mask");
|
|
||||||
p_glUniform1i(loc, 1);
|
|
||||||
|
|
||||||
renderTwoTexture(myNoiseProgram, firstRender);
|
|
||||||
|
|
||||||
// We have rendered, set firstRender to false
|
|
||||||
firstRender = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if bleed filter is enabled
|
|
||||||
if(myFB.myUseBleed)
|
|
||||||
{
|
|
||||||
p_glUseProgram(myBleedProgram);
|
|
||||||
|
|
||||||
// Set some values based on high, medium, or low quality bleed. The high quality
|
|
||||||
// scales by applying additional passes, the low and medium quality scales by using
|
|
||||||
// a width and height based on the zoom level
|
|
||||||
int passes;
|
|
||||||
// High quality
|
|
||||||
if(myFB.myBleedQuality == 2)
|
|
||||||
{
|
|
||||||
// Precalculate pixel shifts
|
|
||||||
GLfloat pH = 1.0 / myHeight;
|
|
||||||
GLfloat pW = 1.0 / myWidth;
|
|
||||||
GLfloat pWx2 = pW * 2.0;
|
|
||||||
|
|
||||||
loc = p_glGetUniformLocation(myBleedProgram, "pH");
|
|
||||||
p_glUniform1f(loc, pH);
|
|
||||||
loc = p_glGetUniformLocation(myBleedProgram, "pW");
|
|
||||||
p_glUniform1f(loc, pW);
|
|
||||||
loc = p_glGetUniformLocation(myBleedProgram, "pWx2");
|
|
||||||
p_glUniform1f(loc, pWx2);
|
|
||||||
|
|
||||||
// Set the number of passes based on zoom level
|
|
||||||
passes = myFB.getZoomLevel();
|
|
||||||
}
|
|
||||||
// Medium and low quality
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// The scaling formula was produced through trial and error
|
|
||||||
// Precalculate pixel shifts
|
|
||||||
GLfloat pH = 1.0 / (myHeight / (0.35 * myFB.getZoomLevel()));
|
|
||||||
GLfloat pW = 1.0 / (myWidth / (0.35 * myFB.getZoomLevel()));
|
|
||||||
GLfloat pWx2 = pW * 2.0;
|
|
||||||
|
|
||||||
loc = p_glGetUniformLocation(myBleedProgram, "pH");
|
|
||||||
p_glUniform1f(loc, pH);
|
|
||||||
loc = p_glGetUniformLocation(myBleedProgram, "pW");
|
|
||||||
p_glUniform1f(loc, pW);
|
|
||||||
loc = p_glGetUniformLocation(myBleedProgram, "pWx2");
|
|
||||||
p_glUniform1f(loc, pWx2);
|
|
||||||
|
|
||||||
// Medium quality
|
|
||||||
if(myFB.myBleedQuality == 1)
|
|
||||||
passes = 2;
|
|
||||||
// Low quality
|
|
||||||
else
|
|
||||||
passes = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we are using a texture effect, we need more bleed
|
|
||||||
if (myFB.myUseTexture)
|
|
||||||
passes <<= 1;
|
|
||||||
|
|
||||||
for (int i = 0; i < passes; i++)
|
|
||||||
{
|
|
||||||
renderTexture(myBleedProgram, firstRender);
|
|
||||||
|
|
||||||
// We have rendered, set firstRender to false
|
|
||||||
firstRender = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if phosphor burn-off filter is enabled
|
|
||||||
if(myFB.myUseGLPhosphor)
|
|
||||||
{
|
|
||||||
p_glUseProgram(myPhosphorProgram);
|
|
||||||
|
|
||||||
// Pass in subpixel mask texture
|
|
||||||
p_glActiveTexture(GL_TEXTURE1);
|
|
||||||
p_glBindTexture(myTexTarget, myPhosphorTexID);
|
|
||||||
loc = p_glGetUniformLocation(myPhosphorProgram, "mask");
|
|
||||||
p_glUniform1i(loc, 1);
|
|
||||||
|
|
||||||
renderTwoTexture(myPhosphorProgram, firstRender);
|
|
||||||
|
|
||||||
p_glActiveTexture(GL_TEXTURE1);
|
|
||||||
p_glBindTexture(myTexTarget, myPhosphorTexID);
|
|
||||||
// We only need to copy the scaled size, which may be smaller than the texture width
|
|
||||||
p_glCopyTexSubImage2D(myTexTarget, 0, 0, 0, myXOrig, myYOrig, myWidth, myHeight);
|
|
||||||
|
|
||||||
// We have rendered, set firstRender to false
|
|
||||||
firstRender = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable all shader programs for the next rendering pass
|
|
||||||
// This is placed here since it's a GLSL 2.0-specific function, and
|
|
||||||
// doesn't exist (and isn't required) for base OpenGL functionality
|
|
||||||
p_glUseProgram(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
mySurfaceIsDirty = false;
|
mySurfaceIsDirty = false;
|
||||||
|
|
||||||
|
@ -1243,223 +814,10 @@ void FBSurfaceGL::update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FBSurfaceGL::renderTexture(GLuint program, bool firstRender)
|
|
||||||
{
|
|
||||||
GLint loc;
|
|
||||||
GLfloat texCoord[4];
|
|
||||||
|
|
||||||
p_glActiveTexture(GL_TEXTURE0);
|
|
||||||
|
|
||||||
// If this is a first render, use the Atari frame buffer
|
|
||||||
if(firstRender)
|
|
||||||
{
|
|
||||||
// Pass in Atari frame
|
|
||||||
p_glBindTexture(myTexTarget, myTexID);
|
|
||||||
p_glTexSubImage2D(myTexTarget, 0, 0, 0, myTexWidth, myTexHeight,
|
|
||||||
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, myTexture->pixels);
|
|
||||||
|
|
||||||
// Set the texture coord appropriately
|
|
||||||
texCoord[0] = myTexCoord[0];
|
|
||||||
texCoord[1] = myTexCoord[1];
|
|
||||||
texCoord[2] = myTexCoord[2];
|
|
||||||
texCoord[3] = myTexCoord[3];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Copy frame buffer to texture, this isn't the fastest way to do it, but it's simple
|
|
||||||
// (rendering directly to texture instead of copying may be faster)
|
|
||||||
p_glBindTexture(myTexTarget, myFilterTexID);
|
|
||||||
// We only need to copy the scaled size, which may be smaller than the texture width
|
|
||||||
p_glCopyTexSubImage2D(myTexTarget, 0, 0, 0, myXOrig, myYOrig, myWidth, myHeight);
|
|
||||||
|
|
||||||
// Set the texture coord appropriately
|
|
||||||
texCoord[0] = myFilterTexCoord[0];
|
|
||||||
texCoord[1] = myFilterTexCoord[1];
|
|
||||||
texCoord[2] = myFilterTexCoord[2];
|
|
||||||
texCoord[3] = myFilterTexCoord[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass the texture to the program
|
|
||||||
loc = p_glGetUniformLocation(program, "tex");
|
|
||||||
p_glUniform1i(loc, 0);
|
|
||||||
|
|
||||||
// Pass in texture as a variable
|
|
||||||
p_glBegin(GL_QUADS);
|
|
||||||
p_glTexCoord2f(texCoord[0], texCoord[1]);
|
|
||||||
p_glVertex2i(myXOrig, myYOrig);
|
|
||||||
|
|
||||||
p_glTexCoord2f(texCoord[2], texCoord[1]);
|
|
||||||
p_glVertex2i(myXOrig + myWidth, myYOrig);
|
|
||||||
|
|
||||||
p_glTexCoord2f(texCoord[2], texCoord[3]);
|
|
||||||
p_glVertex2i(myXOrig + myWidth, myYOrig + myHeight);
|
|
||||||
|
|
||||||
p_glTexCoord2f(texCoord[0], texCoord[3]);
|
|
||||||
p_glVertex2i(myXOrig, myYOrig + myHeight);
|
|
||||||
p_glEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FBSurfaceGL::renderTwoTexture(GLuint program, bool firstRender)
|
|
||||||
{
|
|
||||||
GLint loc;
|
|
||||||
GLfloat texCoord[4];
|
|
||||||
|
|
||||||
p_glActiveTexture(GL_TEXTURE0);
|
|
||||||
|
|
||||||
// If this is a first render, use the Atari frame buffer
|
|
||||||
if(firstRender)
|
|
||||||
{
|
|
||||||
// Pass in Atari frame
|
|
||||||
p_glBindTexture(myTexTarget, myTexID);
|
|
||||||
p_glTexSubImage2D(myTexTarget, 0, 0, 0, myTexWidth, myTexHeight,
|
|
||||||
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, myTexture->pixels);
|
|
||||||
|
|
||||||
// Set the texture coord appropriately
|
|
||||||
texCoord[0] = myTexCoord[0];
|
|
||||||
texCoord[1] = myTexCoord[1];
|
|
||||||
texCoord[2] = myTexCoord[2];
|
|
||||||
texCoord[3] = myTexCoord[3];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Copy frame buffer to texture, this isn't the fastest way to do it, but it's simple
|
|
||||||
// (rendering directly to texture instead of copying may be faster)
|
|
||||||
p_glBindTexture(myTexTarget, myFilterTexID);
|
|
||||||
// We only need to copy the scaled size, which may be smaller than the texture width
|
|
||||||
p_glCopyTexSubImage2D(myTexTarget, 0, 0, 0, myXOrig, myYOrig, myWidth, myHeight);
|
|
||||||
|
|
||||||
// Set the filter texture coord appropriately
|
|
||||||
texCoord[0] = myFilterTexCoord[0];
|
|
||||||
texCoord[1] = myFilterTexCoord[1];
|
|
||||||
texCoord[2] = myFilterTexCoord[2];
|
|
||||||
texCoord[3] = myFilterTexCoord[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass the texture to the program
|
|
||||||
loc = p_glGetUniformLocation(program, "tex");
|
|
||||||
p_glUniform1i(loc, 0);
|
|
||||||
|
|
||||||
// Pass in textures as variables
|
|
||||||
p_glBegin(GL_QUADS);
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE0, texCoord[0], texCoord[1]);
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE1, myFilterTexCoord[0], myFilterTexCoord[1]);
|
|
||||||
p_glVertex2i(myXOrig, myYOrig);
|
|
||||||
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE0, texCoord[2], texCoord[1]);
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE1, myFilterTexCoord[2], myFilterTexCoord[1]);
|
|
||||||
p_glVertex2i(myXOrig + myWidth, myYOrig);
|
|
||||||
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE0, texCoord[2], texCoord[3]);
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE1, myFilterTexCoord[2], myFilterTexCoord[3]);
|
|
||||||
p_glVertex2i(myXOrig + myWidth, myYOrig + myHeight);
|
|
||||||
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE0, texCoord[0], texCoord[3]);
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE1, myFilterTexCoord[0], myFilterTexCoord[3]);
|
|
||||||
p_glVertex2i(myXOrig, myYOrig + myHeight);
|
|
||||||
p_glEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FBSurfaceGL::renderThreeTexture(GLuint program, bool firstRender)
|
|
||||||
{
|
|
||||||
GLint loc;
|
|
||||||
GLfloat texCoord[4];
|
|
||||||
|
|
||||||
p_glActiveTexture(GL_TEXTURE0);
|
|
||||||
|
|
||||||
// If this is a first render, use the Atari frame buffer
|
|
||||||
if(firstRender)
|
|
||||||
{
|
|
||||||
// Pass in Atari frame
|
|
||||||
p_glBindTexture(myTexTarget, myTexID);
|
|
||||||
p_glTexSubImage2D(myTexTarget, 0, 0, 0, myTexWidth, myTexHeight,
|
|
||||||
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, myTexture->pixels);
|
|
||||||
|
|
||||||
// Set the texture coord appropriately
|
|
||||||
texCoord[0] = myTexCoord[0];
|
|
||||||
texCoord[1] = myTexCoord[1];
|
|
||||||
texCoord[2] = myTexCoord[2];
|
|
||||||
texCoord[3] = myTexCoord[3];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Copy frame buffer to texture, this isn't the fastest way to do it, but it's simple
|
|
||||||
// (rendering directly to texture instead of copying may be faster)
|
|
||||||
p_glBindTexture(myTexTarget, myFilterTexID);
|
|
||||||
// We only need to copy the scaled size, which may be smaller than the texture width
|
|
||||||
p_glCopyTexSubImage2D(myTexTarget, 0, 0, 0, myXOrig, myYOrig, myWidth, myHeight);
|
|
||||||
|
|
||||||
// Set the filter texture coord appropriately
|
|
||||||
texCoord[0] = myFilterTexCoord[0];
|
|
||||||
texCoord[1] = myFilterTexCoord[1];
|
|
||||||
texCoord[2] = myFilterTexCoord[2];
|
|
||||||
texCoord[3] = myFilterTexCoord[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass the texture to the program
|
|
||||||
loc = p_glGetUniformLocation(program, "tex");
|
|
||||||
p_glUniform1i(loc, 0);
|
|
||||||
|
|
||||||
// Pass in textures as variables
|
|
||||||
p_glBegin(GL_QUADS);
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE0, texCoord[0], texCoord[1]);
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE1, myFilterTexCoord[0], myFilterTexCoord[1]);
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE2, myFilterTexCoord[0], myFilterTexCoord[1]);
|
|
||||||
p_glVertex2i(myXOrig, myYOrig);
|
|
||||||
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE0, texCoord[2], texCoord[1]);
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE1, myFilterTexCoord[2], myFilterTexCoord[1]);
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE2, myFilterTexCoord[2], myFilterTexCoord[1]);
|
|
||||||
p_glVertex2i(myXOrig + myWidth, myYOrig);
|
|
||||||
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE0, texCoord[2], texCoord[3]);
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE1, myFilterTexCoord[2], myFilterTexCoord[3]);
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE2, myFilterTexCoord[2], myFilterTexCoord[3]);
|
|
||||||
p_glVertex2i(myXOrig + myWidth, myYOrig + myHeight);
|
|
||||||
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE0, texCoord[0], texCoord[3]);
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE1, myFilterTexCoord[0], myFilterTexCoord[3]);
|
|
||||||
p_glMultiTexCoord2f(GL_TEXTURE2, myFilterTexCoord[0], myFilterTexCoord[3]);
|
|
||||||
p_glVertex2i(myXOrig, myYOrig + myHeight);
|
|
||||||
p_glEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceGL::free()
|
void FBSurfaceGL::free()
|
||||||
{
|
{
|
||||||
p_glDeleteTextures(1, &myTexID);
|
p_glDeleteTextures(1, &myTexID);
|
||||||
|
|
||||||
// The below is borken up a bit because of the possible combined texture/noise shader
|
|
||||||
|
|
||||||
if(myFilterTexID)
|
|
||||||
p_glDeleteTextures(1, &myFilterTexID);
|
|
||||||
|
|
||||||
if(mySubMaskTexID)
|
|
||||||
p_glDeleteTextures(1, &mySubMaskTexID);
|
|
||||||
|
|
||||||
if(myTextureProgram)
|
|
||||||
p_glDeleteProgram(myTextureProgram);
|
|
||||||
|
|
||||||
if(myNoiseMaskTexID)
|
|
||||||
{
|
|
||||||
delete[] myNoiseTexture;
|
|
||||||
p_glDeleteTextures(myNoiseNum, myNoiseMaskTexID);
|
|
||||||
delete[] myNoiseMaskTexID;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(myNoiseProgram)
|
|
||||||
p_glDeleteProgram(myNoiseProgram);
|
|
||||||
|
|
||||||
if(myPhosphorTexID)
|
|
||||||
{
|
|
||||||
p_glDeleteTextures(1, &myPhosphorTexID);
|
|
||||||
p_glDeleteProgram(myPhosphorProgram);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(myTextureNoiseProgram)
|
|
||||||
p_glDeleteProgram(myTextureNoiseProgram);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -1488,70 +846,6 @@ void FBSurfaceGL::reload()
|
||||||
p_glTexImage2D(myTexTarget, 0, GL_RGB5,
|
p_glTexImage2D(myTexTarget, 0, GL_RGB5,
|
||||||
myTexWidth, myTexHeight, 0,
|
myTexWidth, myTexHeight, 0,
|
||||||
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, myTexture->pixels);
|
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, myTexture->pixels);
|
||||||
|
|
||||||
// Do the same for the TV filter textures
|
|
||||||
// Only do this if TV filters are enabled
|
|
||||||
if(myTvFiltersEnabled)
|
|
||||||
{
|
|
||||||
// Generate the generic filter texture
|
|
||||||
p_glGenTextures(1, &myFilterTexID);
|
|
||||||
p_glBindTexture(myTexTarget, myFilterTexID);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
// Make the initial texture, this will get overwritten later
|
|
||||||
p_glCopyTexImage2D(myTexTarget, 0, GL_RGB5, 0, 0, myFilterTexWidth, myFilterTexHeight, 0);
|
|
||||||
|
|
||||||
// Only do this if TV and color texture filters are enabled
|
|
||||||
if(myFB.myUseTexture)
|
|
||||||
{
|
|
||||||
// Generate the subpixel mask texture
|
|
||||||
p_glGenTextures(1, &mySubMaskTexID);
|
|
||||||
p_glBindTexture(myTexTarget, mySubMaskTexID);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
// Write the data
|
|
||||||
p_glTexImage2D(myTexTarget, 0, GL_RGB5,
|
|
||||||
myFilterTexWidth, myFilterTexHeight, 0,
|
|
||||||
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, mySubpixelTexture->pixels);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only do this if TV and noise filters are enabled
|
|
||||||
if(myFB.myUseNoise)
|
|
||||||
{
|
|
||||||
// Generate the noise mask textures
|
|
||||||
p_glGenTextures(myNoiseNum, myNoiseMaskTexID);
|
|
||||||
for(int i = 0; i < myNoiseNum; i++)
|
|
||||||
{
|
|
||||||
p_glBindTexture(myTexTarget, myNoiseMaskTexID[i]);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
// Write the data
|
|
||||||
p_glTexImage2D(myTexTarget, 0, GL_RGB5,
|
|
||||||
myFilterTexWidth, myFilterTexHeight, 0,
|
|
||||||
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, myNoiseTexture[i]->pixels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only do this if TV and phosphor filters are enabled
|
|
||||||
if(myFB.myUseGLPhosphor)
|
|
||||||
{
|
|
||||||
// Generate the noise mask textures
|
|
||||||
p_glGenTextures(1, &myPhosphorTexID);
|
|
||||||
p_glBindTexture(myTexTarget, myPhosphorTexID);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
// Make the initial texture, this will get overwritten later
|
|
||||||
p_glCopyTexImage2D(myTexTarget, 0, GL_RGB5, 0, 0, myFilterTexWidth, myFilterTexHeight, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -1568,127 +862,10 @@ void FBSurfaceGL::setFilter(const string& name)
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MIN_FILTER, filter);
|
p_glTexParameteri(myTexTarget, GL_TEXTURE_MIN_FILTER, filter);
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MAG_FILTER, filter);
|
p_glTexParameteri(myTexTarget, GL_TEXTURE_MAG_FILTER, filter);
|
||||||
|
|
||||||
// Do the same for the filter textures
|
|
||||||
// Only do this if TV filters are enabled
|
|
||||||
if(myTvFiltersEnabled)
|
|
||||||
{
|
|
||||||
p_glBindTexture(myTexTarget, myFilterTexID);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MIN_FILTER, filter);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MAG_FILTER, filter);
|
|
||||||
|
|
||||||
// Only do this if TV and color texture filters are enabled
|
|
||||||
if(myFB.myUseTexture)
|
|
||||||
{
|
|
||||||
p_glBindTexture(myTexTarget, mySubMaskTexID);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MIN_FILTER, filter);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MAG_FILTER, filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only do this if TV and noise filters are enabled
|
|
||||||
if(myFB.myUseNoise)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < myNoiseNum; i++)
|
|
||||||
{
|
|
||||||
p_glBindTexture(myTexTarget, myNoiseMaskTexID[i]);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MIN_FILTER, filter);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MAG_FILTER, filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only do this if TV and phosphor filters are enabled
|
|
||||||
if(myFB.myUseGLPhosphor)
|
|
||||||
{
|
|
||||||
p_glBindTexture(myTexTarget, myPhosphorTexID);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MIN_FILTER, filter);
|
|
||||||
p_glTexParameteri(myTexTarget, GL_TEXTURE_MAG_FILTER, filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The filtering has changed, so redraw the entire screen
|
// The filtering has changed, so redraw the entire screen
|
||||||
mySurfaceIsDirty = true;
|
mySurfaceIsDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
GLuint FBSurfaceGL::genShader(ShaderType type)
|
|
||||||
{
|
|
||||||
string fFile = "";
|
|
||||||
char* fCode = NULL;
|
|
||||||
switch(type)
|
|
||||||
{
|
|
||||||
case SHADER_BLEED:
|
|
||||||
fFile = "bleed.frag";
|
|
||||||
fCode = (char*)GLShader::bleed_frag[0];
|
|
||||||
break;
|
|
||||||
case SHADER_TEX:
|
|
||||||
fFile = "texture.frag";
|
|
||||||
fCode = (char*)GLShader::texture_frag[0];
|
|
||||||
break;
|
|
||||||
case SHADER_NOISE:
|
|
||||||
fFile = "noise.frag";
|
|
||||||
fCode = (char*)GLShader::noise_frag[0];
|
|
||||||
break;
|
|
||||||
case SHADER_PHOS:
|
|
||||||
fFile = "phosphor.frag";
|
|
||||||
fCode = (char*)GLShader::phosphor_frag[0];
|
|
||||||
break;
|
|
||||||
case SHADER_TEXNOISE:
|
|
||||||
fFile = "texture_noise.frag";
|
|
||||||
fCode = (char*)GLShader::texture_noise_frag[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// First try opening an external fragment file
|
|
||||||
// These shader files are stored in 'BASEDIR/shaders/'
|
|
||||||
char* buffer = NULL;
|
|
||||||
const string& filename =
|
|
||||||
myFB.myOSystem->baseDir() + "shaders" +
|
|
||||||
BSPF_PATH_SEPARATOR + fFile;
|
|
||||||
ifstream in(filename.c_str());
|
|
||||||
if(in && in.is_open())
|
|
||||||
{
|
|
||||||
// Get file size
|
|
||||||
in.seekg(0, std::ios::end);
|
|
||||||
streampos size = in.tellg();
|
|
||||||
|
|
||||||
// Reset position
|
|
||||||
in.seekg(0);
|
|
||||||
|
|
||||||
// Make buffer of proper size;
|
|
||||||
buffer = new char[size+(streampos)1]; // +1 for '\0'
|
|
||||||
|
|
||||||
// Read in file
|
|
||||||
in.read(buffer, size);
|
|
||||||
buffer[in.gcount()] = '\0';
|
|
||||||
in.close();
|
|
||||||
|
|
||||||
fCode = buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make the shader program
|
|
||||||
GLuint fShader = p_glCreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
GLuint program = p_glCreateProgram();
|
|
||||||
p_glShaderSource(fShader, 1, (const char**)&fCode, NULL);
|
|
||||||
p_glCompileShader(fShader);
|
|
||||||
p_glAttachShader(program, fShader);
|
|
||||||
p_glLinkProgram(program);
|
|
||||||
|
|
||||||
// Go ahead and flag the shader for deletion so it is deleted once the program is
|
|
||||||
p_glDeleteShader(fShader);
|
|
||||||
|
|
||||||
// Clean up
|
|
||||||
delete[] buffer;
|
|
||||||
|
|
||||||
return program;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FrameBufferGL::myLibraryLoaded = false;
|
bool FrameBufferGL::myLibraryLoaded = false;
|
||||||
|
|
||||||
|
|
|
@ -213,24 +213,6 @@ class FrameBufferGL : public FrameBuffer
|
||||||
// Indicates that the texture has been modified, and should be redrawn
|
// Indicates that the texture has been modified, and should be redrawn
|
||||||
bool myDirtyFlag;
|
bool myDirtyFlag;
|
||||||
|
|
||||||
// Indicates whether or not color bleed filter is enabled
|
|
||||||
bool myUseBleed;
|
|
||||||
|
|
||||||
// Indicates the quality of the color bleed filter to use
|
|
||||||
int myBleedQuality;
|
|
||||||
|
|
||||||
// Indicates whether or not color texture filter is enabled
|
|
||||||
bool myUseTexture;
|
|
||||||
|
|
||||||
// Indicates whetehr or not color texture filter is staggered
|
|
||||||
bool myTextureStag;
|
|
||||||
|
|
||||||
// Indicates whether or not the noise filter is enabled
|
|
||||||
bool myUseNoise;
|
|
||||||
|
|
||||||
// Indicates the quality of the noise filter to use
|
|
||||||
int myNoiseQuality;
|
|
||||||
|
|
||||||
// Indicates whether or not the phosphor filter is enabled
|
// Indicates whether or not the phosphor filter is enabled
|
||||||
bool myUseGLPhosphor;
|
bool myUseGLPhosphor;
|
||||||
|
|
||||||
|
@ -286,54 +268,6 @@ class FBSurfaceGL : public FBSurface
|
||||||
private:
|
private:
|
||||||
void setFilter(const string& name);
|
void setFilter(const string& name);
|
||||||
|
|
||||||
/**
|
|
||||||
This method generates an OpenGL shader program from a fragment shader.
|
|
||||||
|
|
||||||
@param fragment The filename of the fragment shader (not including location)
|
|
||||||
|
|
||||||
@return The generated shader program
|
|
||||||
*/
|
|
||||||
enum ShaderType {
|
|
||||||
SHADER_BLEED, SHADER_TEX, SHADER_NOISE, SHADER_PHOS, SHADER_TEXNOISE
|
|
||||||
};
|
|
||||||
GLuint genShader(ShaderType type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method performs the final steps of rendering a single texture filter:
|
|
||||||
passing the previously rendered screen to the given program and drawing
|
|
||||||
to the screen. It does not include setting the program through
|
|
||||||
p_glUseProgram() because this needs to be done before the custom program
|
|
||||||
variables are set.
|
|
||||||
|
|
||||||
@param program The program to use to render the filter
|
|
||||||
@param firstRender True if this is the first render for this frame, false if not
|
|
||||||
*/
|
|
||||||
void renderTexture(GLuint program, bool firstRender);
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method performs the final steps of rendering a two-texture filter:
|
|
||||||
passing the previously rendered screen to the given program and drawing
|
|
||||||
the previous texture and mask texture to the screen. It does not include
|
|
||||||
setting the program through p_glUseProgram() because this needs to be
|
|
||||||
done before the mask texture and custom program variables are set.
|
|
||||||
|
|
||||||
@param program The program to use to render the filter
|
|
||||||
@param firstRender True if this is the first render for this frame, false if not
|
|
||||||
*/
|
|
||||||
void renderTwoTexture(GLuint program, bool firstRender);
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method performs the final steps of rendering a three-texture filter:
|
|
||||||
passing the previously rendered screen to the given program and drawing
|
|
||||||
the previous texture and two mask textures to the screen. It does not include
|
|
||||||
setting the program through p_glUseProgram() because this needs to be
|
|
||||||
done before the mask texture and custom program variables are set.
|
|
||||||
|
|
||||||
@param program The program to use to render the filter
|
|
||||||
@param firstRender True if this is the first render for this frame, false if not
|
|
||||||
*/
|
|
||||||
void renderThreeTexture(GLuint program, bool firstRender);
|
|
||||||
|
|
||||||
void* pixels() const { return myTexture->pixels; }
|
void* pixels() const { return myTexture->pixels; }
|
||||||
uInt32 pitch() const { return myPitch; }
|
uInt32 pitch() const { return myPitch; }
|
||||||
|
|
||||||
|
@ -355,43 +289,9 @@ class FBSurfaceGL : public FBSurface
|
||||||
GLsizei myTexHeight;
|
GLsizei myTexHeight;
|
||||||
GLfloat myTexCoord[4];
|
GLfloat myTexCoord[4];
|
||||||
|
|
||||||
// The filter texture is what is used to hold data from screen after one
|
|
||||||
// filter has been used. Needed since more than one filter is being used.
|
|
||||||
// The size and texture coordinates are also used for the other filter
|
|
||||||
// textures: mySubMaskTexID and myNoiseTexID
|
|
||||||
GLuint myFilterTexID;
|
|
||||||
GLsizei myFilterTexWidth;
|
|
||||||
GLsizei myFilterTexHeight;
|
|
||||||
GLfloat myFilterTexCoord[4];
|
|
||||||
|
|
||||||
// The subpixel texture used for the texture filter
|
|
||||||
GLuint mySubMaskTexID;
|
|
||||||
// The noise textures used for the noise filter
|
|
||||||
GLuint* myNoiseMaskTexID;
|
|
||||||
// The past texture used for the phosphor filter
|
|
||||||
GLuint myPhosphorTexID;
|
|
||||||
|
|
||||||
// Surface for the subpixel texture filter mask
|
|
||||||
SDL_Surface* mySubpixelTexture;
|
|
||||||
// Surfaces for noise filter mask (array of pointers)
|
|
||||||
SDL_Surface** myNoiseTexture;
|
|
||||||
|
|
||||||
uInt32 myXOrig, myYOrig, myWidth, myHeight;
|
uInt32 myXOrig, myYOrig, myWidth, myHeight;
|
||||||
bool mySurfaceIsDirty;
|
bool mySurfaceIsDirty;
|
||||||
uInt32 myPitch;
|
uInt32 myPitch;
|
||||||
|
|
||||||
// OpenGL shader programs
|
|
||||||
GLuint myBleedProgram; // Shader for color bleed filter
|
|
||||||
GLuint myTextureProgram; // Shader for color texture filter
|
|
||||||
GLuint myNoiseProgram; // Shader for noise filter
|
|
||||||
GLuint myPhosphorProgram; // Shader for the phosphor filter
|
|
||||||
GLuint myTextureNoiseProgram; // Shader for both color texture and noise filters
|
|
||||||
|
|
||||||
// Used to save the number of noise textures to use at game launch
|
|
||||||
int myNoiseNum;
|
|
||||||
|
|
||||||
// Specifies whether the TV filters can be applied to this surface
|
|
||||||
bool myTvFiltersEnabled;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DISPLAY_OPENGL
|
#endif // DISPLAY_OPENGL
|
||||||
|
|
|
@ -38,17 +38,16 @@ SoundNull::~SoundNull()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool SoundNull::load(Serializer& in)
|
bool SoundNull::load(Serializer& in)
|
||||||
{
|
{
|
||||||
const string& soundDevice = "TIASound";
|
if(in.getString() != "TIASound")
|
||||||
if(in.getString() != soundDevice)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uInt8 reg;
|
// Read sound registers and discard
|
||||||
reg = (uInt8) in.getByte();
|
in.getByte();
|
||||||
reg = (uInt8) in.getByte();
|
in.getByte();
|
||||||
reg = (uInt8) in.getByte();
|
in.getByte();
|
||||||
reg = (uInt8) in.getByte();
|
in.getByte();
|
||||||
reg = (uInt8) in.getByte();
|
in.getByte();
|
||||||
reg = (uInt8) in.getByte();
|
in.getByte();
|
||||||
|
|
||||||
// myLastRegisterSetCycle
|
// myLastRegisterSetCycle
|
||||||
in.getInt();
|
in.getInt();
|
||||||
|
@ -61,13 +60,12 @@ bool SoundNull::save(Serializer& out) const
|
||||||
{
|
{
|
||||||
out.putString("TIASound");
|
out.putString("TIASound");
|
||||||
|
|
||||||
uInt8 reg = 0;
|
out.putByte(0);
|
||||||
out.putByte((char)reg);
|
out.putByte(0);
|
||||||
out.putByte((char)reg);
|
out.putByte(0);
|
||||||
out.putByte((char)reg);
|
out.putByte(0);
|
||||||
out.putByte((char)reg);
|
out.putByte(0);
|
||||||
out.putByte((char)reg);
|
out.putByte(0);
|
||||||
out.putByte((char)reg);
|
|
||||||
|
|
||||||
// myLastRegisterSetCycle
|
// myLastRegisterSetCycle
|
||||||
out.putInt(0);
|
out.putInt(0);
|
||||||
|
|
|
@ -1014,15 +1014,11 @@ void CartDebug::addressTypeAsString(ostream& buf, uInt16 addr) const
|
||||||
debugger = myDebugger.getAccessFlags(addr) & 0xFC,
|
debugger = myDebugger.getAccessFlags(addr) & 0xFC,
|
||||||
label = myDisLabels[addr & 0xFFF];
|
label = myDisLabels[addr & 0xFFF];
|
||||||
|
|
||||||
string s1 = Debugger::to_bin_8(directive),
|
buf << endl << "directive: " << myDebugger.valueToString(directive, kBASE_2_8) << " ";
|
||||||
s2 = Debugger::to_bin_8(debugger),
|
|
||||||
s3 = Debugger::to_bin_8(label);
|
|
||||||
|
|
||||||
buf << endl << "directive: " << s1 << " ";
|
|
||||||
disasmTypeAsString(buf, directive);
|
disasmTypeAsString(buf, directive);
|
||||||
buf << endl << "emulation: " << s2 << " ";
|
buf << endl << "emulation: " << myDebugger.valueToString(debugger, kBASE_2_8) << " ";
|
||||||
disasmTypeAsString(buf, debugger);
|
disasmTypeAsString(buf, debugger);
|
||||||
buf << endl << "tentative: " << s3 << " ";
|
buf << endl << "tentative: " << myDebugger.valueToString(label, kBASE_2_8) << " ";
|
||||||
disasmTypeAsString(buf, label);
|
disasmTypeAsString(buf, label);
|
||||||
buf << endl;
|
buf << endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -293,45 +293,60 @@ const string Debugger::run(const string& command)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
string Debugger::valueToString(int value, BaseFormat outputBase)
|
string Debugger::valueToString(int value, BaseFormat outputBase) const
|
||||||
{
|
{
|
||||||
char buf[32];
|
static char vToS_buf[32];
|
||||||
|
|
||||||
if(outputBase == kBASE_DEFAULT)
|
if(outputBase == kBASE_DEFAULT)
|
||||||
outputBase = myParser->base();
|
outputBase = myParser->base();
|
||||||
|
|
||||||
switch(outputBase)
|
switch(outputBase)
|
||||||
{
|
{
|
||||||
case kBASE_2:
|
case kBASE_2: // base 2: 8 or 16 bits (depending on value)
|
||||||
|
case kBASE_2_8: // base 2: 1 byte (8 bits) wide
|
||||||
|
case kBASE_2_16: // base 2: 2 bytes (16 bits) wide
|
||||||
|
{
|
||||||
|
int places = (outputBase == kBASE_2_8 ||
|
||||||
|
(outputBase == kBASE_2 && value < 0x100)) ? 8 : 16;
|
||||||
|
vToS_buf[places] = '\0';
|
||||||
|
int bit = 1;
|
||||||
|
while(--places >= 0) {
|
||||||
|
if(value & bit) vToS_buf[places] = '1';
|
||||||
|
else vToS_buf[places] = '0';
|
||||||
|
bit <<= 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case kBASE_10: // base 10: 3 or 5 bytes (depending on value)
|
||||||
if(value < 0x100)
|
if(value < 0x100)
|
||||||
Debugger::to_bin(value, 8, buf);
|
snprintf(vToS_buf, 4, "%3d", value);
|
||||||
else
|
else
|
||||||
Debugger::to_bin(value, 16, buf);
|
snprintf(vToS_buf, 6, "%5d", value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kBASE_10:
|
case kBASE_16_1: // base 16: 1 byte wide
|
||||||
if(value < 0x100)
|
snprintf(vToS_buf, 2, "%1X", value);
|
||||||
sprintf(buf, "%3d", value);
|
break;
|
||||||
else
|
case kBASE_16_2: // base 16: 2 bytes wide
|
||||||
sprintf(buf, "%5d", value);
|
snprintf(vToS_buf, 3, "%02X", value);
|
||||||
|
break;
|
||||||
|
case kBASE_16_4: // base 16: 4 bytes wide
|
||||||
|
snprintf(vToS_buf, 5, "%04X", value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kBASE_16_4:
|
case kBASE_16: // base 16: 2, 4, 8 bytes (depending on value)
|
||||||
strcpy(buf, Debugger::to_hex_4(value));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case kBASE_16:
|
|
||||||
default:
|
default:
|
||||||
if(value < 0x100)
|
if(value < 0x100)
|
||||||
sprintf(buf, "%02X", value);
|
snprintf(vToS_buf, 3, "%02X", value);
|
||||||
else if(value < 0x10000)
|
else if(value < 0x10000)
|
||||||
sprintf(buf, "%04X", value);
|
snprintf(vToS_buf, 5, "%04X", value);
|
||||||
else
|
else
|
||||||
sprintf(buf, "%08X", value);
|
snprintf(vToS_buf, 9, "%08X", value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(buf);
|
return string(vToS_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -182,51 +182,7 @@ class Debugger : public DialogContainer
|
||||||
*/
|
*/
|
||||||
int stringToValue(const string& stringval)
|
int stringToValue(const string& stringval)
|
||||||
{ return myParser->decipher_arg(stringval); }
|
{ return myParser->decipher_arg(stringval); }
|
||||||
string valueToString(int value, BaseFormat outputBase = kBASE_DEFAULT);
|
string valueToString(int value, BaseFormat outputBase = kBASE_DEFAULT) const;
|
||||||
|
|
||||||
/** Convenience methods to convert to/from base values */
|
|
||||||
static char* to_hex_4(int i)
|
|
||||||
{
|
|
||||||
static char out[2];
|
|
||||||
sprintf(out, "%1X", i);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
static char* to_hex_8(int i)
|
|
||||||
{
|
|
||||||
static char out[3];
|
|
||||||
sprintf(out, "%02X", i);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
static char* to_hex_16(int i)
|
|
||||||
{
|
|
||||||
static char out[5];
|
|
||||||
sprintf(out, "%04X", i);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
static char* to_bin(int dec, int places, char *buf) {
|
|
||||||
int bit = 1;
|
|
||||||
buf[places] = '\0';
|
|
||||||
while(--places >= 0) {
|
|
||||||
if(dec & bit) buf[places] = '1';
|
|
||||||
else buf[places] = '0';
|
|
||||||
bit <<= 1;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
static char* to_bin_8(int dec) {
|
|
||||||
static char buf[9];
|
|
||||||
return to_bin(dec, 8, buf);
|
|
||||||
}
|
|
||||||
static char* to_bin_16(int dec) {
|
|
||||||
static char buf[17];
|
|
||||||
return to_bin(dec, 16, buf);
|
|
||||||
}
|
|
||||||
static int conv_hex_digit(char d) {
|
|
||||||
if(d >= '0' && d <= '9') return d - '0';
|
|
||||||
else if(d >= 'a' && d <= 'f') return d - 'a' + 10;
|
|
||||||
else if(d >= 'A' && d <= 'F') return d - 'A' + 10;
|
|
||||||
else return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convenience methods to get/set bit(s) in an 8-bit register */
|
/* Convenience methods to get/set bit(s) in an 8-bit register */
|
||||||
static uInt8 set_bit(uInt8 input, uInt8 bit, bool on)
|
static uInt8 set_bit(uInt8 input, uInt8 bit, bool on)
|
||||||
|
|
|
@ -265,7 +265,11 @@ int DebuggerParser::decipher_arg(const string &str)
|
||||||
} else { // must be hex.
|
} else { // must be hex.
|
||||||
result = 0;
|
result = 0;
|
||||||
while(*a != '\0') {
|
while(*a != '\0') {
|
||||||
int hex = Debugger::conv_hex_digit(*a++);
|
int hex = -1;
|
||||||
|
char d = *a++;
|
||||||
|
if(d >= '0' && d <= '9') hex = d - '0';
|
||||||
|
else if(d >= 'a' && d <= 'f') hex = d - 'a' + 10;
|
||||||
|
else if(d >= 'A' && d <= 'F') hex = d - 'A' + 10;
|
||||||
if(hex < 0)
|
if(hex < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -525,30 +529,38 @@ cerr << "curCount = " << curCount << endl
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
string DebuggerParser::eval()
|
string DebuggerParser::eval()
|
||||||
{
|
{
|
||||||
char buf[50];
|
ostringstream buf;
|
||||||
string ret;
|
for(int i = 0; i < argCount; ++i)
|
||||||
for(int i=0; i<argCount; i++) {
|
{
|
||||||
// TODO - technically, we should determine if the label is read or write
|
string rlabel = debugger->cartDebug().getLabel(args[i], true);
|
||||||
const string& label = debugger->cartDebug().getLabel(args[i], true);
|
string wlabel = debugger->cartDebug().getLabel(args[i], false);
|
||||||
if(label != "") {
|
bool validR = rlabel != "" && rlabel[0] != '$',
|
||||||
ret += label;
|
validW = wlabel != "" && wlabel[0] != '$';
|
||||||
ret += ": ";
|
if(validR && validW)
|
||||||
|
{
|
||||||
|
if(rlabel == wlabel)
|
||||||
|
buf << rlabel << "(R/W): ";
|
||||||
|
else
|
||||||
|
buf << rlabel << "(R) / " << wlabel << "(W): ";
|
||||||
}
|
}
|
||||||
ret += "$";
|
else if(validR)
|
||||||
if(args[i] < 0x100) {
|
buf << rlabel << "(R): ";
|
||||||
ret += Debugger::to_hex_8(args[i]);
|
else if(validW)
|
||||||
ret += " %";
|
buf << wlabel << "(W): ";
|
||||||
ret += Debugger::to_bin_8(args[i]);
|
|
||||||
} else {
|
if(args[i] < 0x100)
|
||||||
ret += Debugger::to_hex_16(args[i]);
|
buf << "$" << debugger->valueToString(args[i], kBASE_16_2)
|
||||||
ret += " %";
|
<< " %" << debugger->valueToString(args[i], kBASE_2_8);
|
||||||
ret += Debugger::to_bin_16(args[i]);
|
else
|
||||||
}
|
buf << "$" << debugger->valueToString(args[i], kBASE_16_4)
|
||||||
sprintf(buf, " #%d", args[i]);
|
<< " %" << debugger->valueToString(args[i], kBASE_2_16);
|
||||||
ret += buf;
|
|
||||||
if(i != argCount - 1) ret += "\n";
|
buf << " #" << (int) args[i];
|
||||||
|
if(i != argCount - 1)
|
||||||
|
buf << endl;
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
|
return buf.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -30,12 +30,19 @@ struct Command;
|
||||||
#include "Array.hxx"
|
#include "Array.hxx"
|
||||||
#include "FrameBuffer.hxx"
|
#include "FrameBuffer.hxx"
|
||||||
|
|
||||||
|
// The base to use for conversion from integers to strings
|
||||||
|
// Note that the actual number of places will be determined by
|
||||||
|
// the magnitude of the value itself in the general case
|
||||||
typedef enum {
|
typedef enum {
|
||||||
kBASE_16,
|
kBASE_16, // base 16: 2, 4, 8 bytes (depending on value)
|
||||||
kBASE_16_4,
|
kBASE_16_1, // base 16: 1 byte wide
|
||||||
kBASE_10,
|
kBASE_16_2, // base 16: 2 bytes wide
|
||||||
kBASE_2,
|
kBASE_16_4, // base 16: 4 bytes wide
|
||||||
kBASE_DEFAULT
|
kBASE_10, // base 10: 3 or 5 bytes (depending on value)
|
||||||
|
kBASE_2, // base 2: 8 or 16 bits (depending on value)
|
||||||
|
kBASE_2_8, // base 2: 1 byte (8 bits) wide
|
||||||
|
kBASE_2_16, // base 2: 2 bytes (16 bits) wide
|
||||||
|
kBASE_DEFAULT
|
||||||
} BaseFormat;
|
} BaseFormat;
|
||||||
|
|
||||||
class DebuggerParser
|
class DebuggerParser
|
||||||
|
@ -62,7 +69,7 @@ class DebuggerParser
|
||||||
|
|
||||||
/** Get/set the number base when parsing numeric values */
|
/** Get/set the number base when parsing numeric values */
|
||||||
void setBase(BaseFormat base) { defaultBase = base; }
|
void setBase(BaseFormat base) { defaultBase = base; }
|
||||||
BaseFormat base() { return defaultBase; }
|
BaseFormat base() const { return defaultBase; }
|
||||||
|
|
||||||
static inline string red(const string& msg = "")
|
static inline string red(const string& msg = "")
|
||||||
{
|
{
|
||||||
|
|
|
@ -229,7 +229,7 @@ void DiStella::disasm(uInt32 distart, int pass)
|
||||||
myDisasmBuf << ((c > 127) ? bit_string : " ");
|
myDisasmBuf << ((c > 127) ? bit_string : " ");
|
||||||
myDisasmBuf << "| $" << HEX4 << myPC+myOffset << "'";
|
myDisasmBuf << "| $" << HEX4 << myPC+myOffset << "'";
|
||||||
if(settings.gfx_format == kBASE_2)
|
if(settings.gfx_format == kBASE_2)
|
||||||
myDisasmBuf << Debugger::to_bin_8(byte);
|
myDisasmBuf << Debugger::debugger().valueToString(byte, kBASE_2_8);
|
||||||
else
|
else
|
||||||
myDisasmBuf << HEX2 << (int)byte;
|
myDisasmBuf << HEX2 << (int)byte;
|
||||||
addEntry(isPGfx ? CartDebug::PGFX : CartDebug::GFX);
|
addEntry(isPGfx ? CartDebug::PGFX : CartDebug::GFX);
|
||||||
|
|
|
@ -774,14 +774,14 @@ string TIADebug::toString()
|
||||||
<< "BK=" << myDebugger.valueToString(state.coluRegs[3]) << "/"
|
<< "BK=" << myDebugger.valueToString(state.coluRegs[3]) << "/"
|
||||||
<< colorSwatch(state.coluRegs[3])
|
<< colorSwatch(state.coluRegs[3])
|
||||||
<< endl
|
<< endl
|
||||||
<< "P0: GR=" << string(Debugger::to_bin_8(state.gr[P0]))
|
<< "P0: GR=" << myDebugger.valueToString(state.gr[P0], kBASE_2_8)
|
||||||
<< " pos=" << myDebugger.valueToString(state.pos[P0])
|
<< " pos=" << myDebugger.valueToString(state.pos[P0])
|
||||||
<< " HM=" << myDebugger.valueToString(state.hm[P0]) << " "
|
<< " HM=" << myDebugger.valueToString(state.hm[P0]) << " "
|
||||||
<< nusizP0String() << " "
|
<< nusizP0String() << " "
|
||||||
<< booleanWithLabel("refl", refP0()) << " "
|
<< booleanWithLabel("refl", refP0()) << " "
|
||||||
<< booleanWithLabel("delay", vdelP0())
|
<< booleanWithLabel("delay", vdelP0())
|
||||||
<< endl
|
<< endl
|
||||||
<< "P1: GR=" << string(Debugger::to_bin_8(state.gr[P1]))
|
<< "P1: GR=" << myDebugger.valueToString(state.gr[P1], kBASE_2_8)
|
||||||
<< " pos=" << myDebugger.valueToString(state.pos[P1])
|
<< " pos=" << myDebugger.valueToString(state.pos[P1])
|
||||||
<< " HM=" << myDebugger.valueToString(state.hm[P1]) << " "
|
<< " HM=" << myDebugger.valueToString(state.hm[P1]) << " "
|
||||||
<< nusizP1String() << " "
|
<< nusizP1String() << " "
|
||||||
|
@ -806,11 +806,11 @@ string TIADebug::toString()
|
||||||
<< " size=" << myDebugger.valueToString(state.size[BL]) << " "
|
<< " size=" << myDebugger.valueToString(state.size[BL]) << " "
|
||||||
<< booleanWithLabel("delay", vdelBL())
|
<< booleanWithLabel("delay", vdelBL())
|
||||||
<< endl
|
<< endl
|
||||||
<< "PF0: " << string(Debugger::to_bin_8(state.pf[0])) << "/"
|
<< "PF0: " << myDebugger.valueToString(state.pf[0], kBASE_2_8) << "/"
|
||||||
<< myDebugger.valueToString(state.pf[0])
|
<< myDebugger.valueToString(state.pf[0])
|
||||||
<< " PF1: " << string(Debugger::to_bin_8(state.pf[1])) << "/"
|
<< " PF1: " << myDebugger.valueToString(state.pf[1], kBASE_2_8) << "/"
|
||||||
<< myDebugger.valueToString(state.pf[1])
|
<< myDebugger.valueToString(state.pf[1])
|
||||||
<< " PF2: " << string(Debugger::to_bin_8(state.pf[2])) << "/"
|
<< " PF2: " << myDebugger.valueToString(state.pf[2], kBASE_2_8) << "/"
|
||||||
<< myDebugger.valueToString(state.pf[2])
|
<< myDebugger.valueToString(state.pf[2])
|
||||||
<< endl << " "
|
<< endl << " "
|
||||||
<< booleanWithLabel("reflect", refPF()) << " "
|
<< booleanWithLabel("reflect", refPF()) << " "
|
||||||
|
|
|
@ -66,7 +66,8 @@ AudioWidget::AudioWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
{
|
{
|
||||||
new StaticTextWidget(boss, font, xpos + col*myAudF->colWidth() + 7,
|
new StaticTextWidget(boss, font, xpos + col*myAudF->colWidth() + 7,
|
||||||
ypos - lineHeight, fontWidth, fontHeight,
|
ypos - lineHeight, fontWidth, fontHeight,
|
||||||
Debugger::to_hex_4(col), kTextAlignLeft);
|
instance().debugger().valueToString(col, kBASE_16_1),
|
||||||
|
kTextAlignLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
// AudC registers
|
// AudC registers
|
||||||
|
|
|
@ -244,7 +244,15 @@ void DataGridWidget::handleMouseUp(int x, int y, int button, int clickCount)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DataGridWidget::handleMouseWheel(int x, int y, int direction)
|
void DataGridWidget::handleMouseWheel(int x, int y, int direction)
|
||||||
{
|
{
|
||||||
_scrollBar->handleMouseWheel(x, y, direction);
|
if(_scrollBar)
|
||||||
|
_scrollBar->handleMouseWheel(x, y, direction);
|
||||||
|
else if(_editable)
|
||||||
|
{
|
||||||
|
if(direction > 0)
|
||||||
|
decrementCell();
|
||||||
|
else if(direction < 0)
|
||||||
|
incrementCell();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -96,7 +96,7 @@ RamWidget::RamWidget(GuiObject* boss, const GUI::Font& font, int x, int y)
|
||||||
new StaticTextWidget(boss, font, xpos + col*myRamGrid->colWidth() + lwidth + 8,
|
new StaticTextWidget(boss, font, xpos + col*myRamGrid->colWidth() + lwidth + 8,
|
||||||
ypos - lineHeight,
|
ypos - lineHeight,
|
||||||
fontWidth, fontHeight,
|
fontWidth, fontHeight,
|
||||||
Debugger::to_hex_4(col),
|
instance().debugger().valueToString(col, kBASE_16_1),
|
||||||
kTextAlignLeft);
|
kTextAlignLeft);
|
||||||
}
|
}
|
||||||
for(int row = 0; row < 8; ++row)
|
for(int row = 0; row < 8; ++row)
|
||||||
|
|
|
@ -70,7 +70,7 @@ TiaWidget::TiaWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
t = new StaticTextWidget(boss, font, xpos + col*myRamGrid->colWidth() + lwidth + 7,
|
t = new StaticTextWidget(boss, font, xpos + col*myRamGrid->colWidth() + lwidth + 7,
|
||||||
ypos - lineHeight,
|
ypos - lineHeight,
|
||||||
fontWidth, fontHeight,
|
fontWidth, fontHeight,
|
||||||
Debugger::to_hex_4(col),
|
instance().debugger().valueToString(col, kBASE_16_1),
|
||||||
kTextAlignLeft);
|
kTextAlignLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ TiaWidget::TiaWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
"HM:", kTextAlignLeft);
|
"HM:", kTextAlignLeft);
|
||||||
xpos += 3*fontWidth + 5;
|
xpos += 3*fontWidth + 5;
|
||||||
myHMP0 = new DataGridWidget(boss, font, xpos, ypos,
|
myHMP0 = new DataGridWidget(boss, font, xpos, ypos,
|
||||||
1, 1, 1, 4, kBASE_16_4);
|
1, 1, 1, 4, kBASE_16_1);
|
||||||
myHMP0->setTarget(this);
|
myHMP0->setTarget(this);
|
||||||
myHMP0->setID(kHMP0ID);
|
myHMP0->setID(kHMP0ID);
|
||||||
addFocusWidget(myHMP0);
|
addFocusWidget(myHMP0);
|
||||||
|
@ -294,7 +294,7 @@ TiaWidget::TiaWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
"NusizP0:", kTextAlignLeft);
|
"NusizP0:", kTextAlignLeft);
|
||||||
xpos += 8*fontWidth + 5;
|
xpos += 8*fontWidth + 5;
|
||||||
myNusizP0 = new DataGridWidget(boss, font, xpos, ypos,
|
myNusizP0 = new DataGridWidget(boss, font, xpos, ypos,
|
||||||
1, 1, 1, 3, kBASE_16_4);
|
1, 1, 1, 3, kBASE_16_1);
|
||||||
myNusizP0->setTarget(this);
|
myNusizP0->setTarget(this);
|
||||||
myNusizP0->setID(kNusizP0ID);
|
myNusizP0->setID(kNusizP0ID);
|
||||||
addFocusWidget(myNusizP0);
|
addFocusWidget(myNusizP0);
|
||||||
|
@ -334,7 +334,7 @@ TiaWidget::TiaWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
"HM:", kTextAlignLeft);
|
"HM:", kTextAlignLeft);
|
||||||
xpos += 3*fontWidth + 5;
|
xpos += 3*fontWidth + 5;
|
||||||
myHMP1 = new DataGridWidget(boss, font, xpos, ypos,
|
myHMP1 = new DataGridWidget(boss, font, xpos, ypos,
|
||||||
1, 1, 1, 4, kBASE_16_4);
|
1, 1, 1, 4, kBASE_16_1);
|
||||||
myHMP1->setTarget(this);
|
myHMP1->setTarget(this);
|
||||||
myHMP1->setID(kHMP1ID);
|
myHMP1->setID(kHMP1ID);
|
||||||
addFocusWidget(myHMP1);
|
addFocusWidget(myHMP1);
|
||||||
|
@ -360,7 +360,7 @@ TiaWidget::TiaWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
"NusizP1:", kTextAlignLeft);
|
"NusizP1:", kTextAlignLeft);
|
||||||
xpos += 8*fontWidth + 5;
|
xpos += 8*fontWidth + 5;
|
||||||
myNusizP1 = new DataGridWidget(boss, font, xpos, ypos,
|
myNusizP1 = new DataGridWidget(boss, font, xpos, ypos,
|
||||||
1, 1, 1, 3, kBASE_16_4);
|
1, 1, 1, 3, kBASE_16_1);
|
||||||
myNusizP1->setTarget(this);
|
myNusizP1->setTarget(this);
|
||||||
myNusizP1->setID(kNusizP1ID);
|
myNusizP1->setID(kNusizP1ID);
|
||||||
addFocusWidget(myNusizP1);
|
addFocusWidget(myNusizP1);
|
||||||
|
@ -401,7 +401,7 @@ TiaWidget::TiaWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
"HM:", kTextAlignLeft);
|
"HM:", kTextAlignLeft);
|
||||||
xpos += 3*fontWidth + 5;
|
xpos += 3*fontWidth + 5;
|
||||||
myHMM0 = new DataGridWidget(boss, font, xpos, ypos,
|
myHMM0 = new DataGridWidget(boss, font, xpos, ypos,
|
||||||
1, 1, 1, 4, kBASE_16_4);
|
1, 1, 1, 4, kBASE_16_1);
|
||||||
myHMM0->setTarget(this);
|
myHMM0->setTarget(this);
|
||||||
myHMM0->setID(kHMM0ID);
|
myHMM0->setID(kHMM0ID);
|
||||||
addFocusWidget(myHMM0);
|
addFocusWidget(myHMM0);
|
||||||
|
@ -412,7 +412,7 @@ TiaWidget::TiaWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
"Size:", kTextAlignLeft);
|
"Size:", kTextAlignLeft);
|
||||||
xpos += 5*fontWidth + 5;
|
xpos += 5*fontWidth + 5;
|
||||||
myNusizM0 = new DataGridWidget(boss, font, xpos, ypos,
|
myNusizM0 = new DataGridWidget(boss, font, xpos, ypos,
|
||||||
1, 1, 1, 2, kBASE_16_4);
|
1, 1, 1, 2, kBASE_16_1);
|
||||||
myNusizM0->setTarget(this);
|
myNusizM0->setTarget(this);
|
||||||
myNusizM0->setID(kNusizM0ID);
|
myNusizM0->setID(kNusizM0ID);
|
||||||
addFocusWidget(myNusizM0);
|
addFocusWidget(myNusizM0);
|
||||||
|
@ -456,7 +456,7 @@ TiaWidget::TiaWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
"HM:", kTextAlignLeft);
|
"HM:", kTextAlignLeft);
|
||||||
xpos += 3*fontWidth + 5;
|
xpos += 3*fontWidth + 5;
|
||||||
myHMM1 = new DataGridWidget(boss, font, xpos, ypos,
|
myHMM1 = new DataGridWidget(boss, font, xpos, ypos,
|
||||||
1, 1, 1, 4, kBASE_16_4);
|
1, 1, 1, 4, kBASE_16_1);
|
||||||
myHMM1->setTarget(this);
|
myHMM1->setTarget(this);
|
||||||
myHMM1->setID(kHMM1ID);
|
myHMM1->setID(kHMM1ID);
|
||||||
addFocusWidget(myHMM1);
|
addFocusWidget(myHMM1);
|
||||||
|
@ -467,7 +467,7 @@ TiaWidget::TiaWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
"Size:", kTextAlignLeft);
|
"Size:", kTextAlignLeft);
|
||||||
xpos += 5*fontWidth + 5;
|
xpos += 5*fontWidth + 5;
|
||||||
myNusizM1 = new DataGridWidget(boss, font, xpos, ypos,
|
myNusizM1 = new DataGridWidget(boss, font, xpos, ypos,
|
||||||
1, 1, 1, 2, kBASE_16_4);
|
1, 1, 1, 2, kBASE_16_1);
|
||||||
myNusizM1->setTarget(this);
|
myNusizM1->setTarget(this);
|
||||||
myNusizM1->setID(kNusizM1ID);
|
myNusizM1->setID(kNusizM1ID);
|
||||||
addFocusWidget(myNusizM1);
|
addFocusWidget(myNusizM1);
|
||||||
|
@ -511,7 +511,7 @@ TiaWidget::TiaWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
"HM:", kTextAlignLeft);
|
"HM:", kTextAlignLeft);
|
||||||
xpos += 3*fontWidth + 5;
|
xpos += 3*fontWidth + 5;
|
||||||
myHMBL = new DataGridWidget(boss, font, xpos, ypos,
|
myHMBL = new DataGridWidget(boss, font, xpos, ypos,
|
||||||
1, 1, 1, 4, kBASE_16_4);
|
1, 1, 1, 4, kBASE_16_1);
|
||||||
myHMBL->setTarget(this);
|
myHMBL->setTarget(this);
|
||||||
myHMBL->setID(kHMBLID);
|
myHMBL->setID(kHMBLID);
|
||||||
addFocusWidget(myHMBL);
|
addFocusWidget(myHMBL);
|
||||||
|
@ -522,7 +522,7 @@ TiaWidget::TiaWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
"Size:", kTextAlignLeft);
|
"Size:", kTextAlignLeft);
|
||||||
xpos += 5*fontWidth + 5;
|
xpos += 5*fontWidth + 5;
|
||||||
mySizeBL = new DataGridWidget(boss, font, xpos, ypos,
|
mySizeBL = new DataGridWidget(boss, font, xpos, ypos,
|
||||||
1, 1, 1, 2, kBASE_16_4);
|
1, 1, 1, 2, kBASE_16_1);
|
||||||
mySizeBL->setTarget(this);
|
mySizeBL->setTarget(this);
|
||||||
mySizeBL->setID(kSizeBLID);
|
mySizeBL->setID(kSizeBLID);
|
||||||
addFocusWidget(mySizeBL);
|
addFocusWidget(mySizeBL);
|
||||||
|
|
|
@ -240,71 +240,7 @@ VideoDialog::VideoDialog(OSystem* osystem, DialogContainer* parent,
|
||||||
wid.clear();
|
wid.clear();
|
||||||
tabID = myTab->addTab(" TV Effects ");
|
tabID = myTab->addTab(" TV Effects ");
|
||||||
xpos = ypos = 8;
|
xpos = ypos = 8;
|
||||||
lwidth = font.getStringWidth("TV Color Texture: ");
|
// TODO ...
|
||||||
pwidth = font.getStringWidth("Staggered");
|
|
||||||
|
|
||||||
// Use TV color texture effect
|
|
||||||
items.clear();
|
|
||||||
items.push_back("Off", "off");
|
|
||||||
items.push_back("Normal", "normal");
|
|
||||||
items.push_back("Staggered", "stag");
|
|
||||||
myTexturePopup =
|
|
||||||
new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, items,
|
|
||||||
"TV Color Texture: ", lwidth);
|
|
||||||
wid.push_back(myTexturePopup);
|
|
||||||
ypos += lineHeight + 4;
|
|
||||||
|
|
||||||
// Use color bleed effect
|
|
||||||
items.clear();
|
|
||||||
items.push_back("Off", "off");
|
|
||||||
items.push_back("Low", "low");
|
|
||||||
items.push_back("Medium", "medium");
|
|
||||||
items.push_back("High", "high");
|
|
||||||
myBleedPopup =
|
|
||||||
new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, items,
|
|
||||||
"TV Color Bleed: ", lwidth);
|
|
||||||
wid.push_back(myBleedPopup);
|
|
||||||
ypos += lineHeight + 4;
|
|
||||||
|
|
||||||
// Use image noise effect
|
|
||||||
items.clear();
|
|
||||||
items.push_back("Off", "off");
|
|
||||||
items.push_back("Low", "low");
|
|
||||||
items.push_back("Medium", "medium");
|
|
||||||
items.push_back("High", "high");
|
|
||||||
myNoisePopup =
|
|
||||||
new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, items,
|
|
||||||
"TV Image Noise: ", lwidth);
|
|
||||||
wid.push_back(myNoisePopup);
|
|
||||||
ypos += lineHeight + 4;
|
|
||||||
|
|
||||||
// Use phosphor burn-off effect
|
|
||||||
ypos += 4;
|
|
||||||
myPhosphorCheckbox =
|
|
||||||
new CheckboxWidget(myTab, font, xpos, ypos, "TV Phosphor Burn-off");
|
|
||||||
wid.push_back(myPhosphorCheckbox);
|
|
||||||
ypos += lineHeight + 4;
|
|
||||||
|
|
||||||
// OpenGL information
|
|
||||||
// Add message concerning GLSL requirement
|
|
||||||
ypos += lineHeight + 4;
|
|
||||||
lwidth = font.getStringWidth("(*) TV effects require OpenGL 2.0+ & GLSL");
|
|
||||||
new StaticTextWidget(myTab, font, 10, ypos, lwidth, fontHeight,
|
|
||||||
"(*) TV effects require OpenGL 2.0+ & GLSL",
|
|
||||||
kTextAlignLeft);
|
|
||||||
ypos += lineHeight + 4;
|
|
||||||
new StaticTextWidget(myTab, font, 10+font.getStringWidth("(*) "), ypos,
|
|
||||||
lwidth, fontHeight, "\'gl_texrect\' must be disabled",
|
|
||||||
kTextAlignLeft);
|
|
||||||
ypos += lineHeight + 10;
|
|
||||||
|
|
||||||
myGLVersionInfo =
|
|
||||||
new StaticTextWidget(myTab, font, 10+font.getStringWidth("(*) "), ypos,
|
|
||||||
lwidth, fontHeight, "", kTextAlignLeft);
|
|
||||||
ypos += lineHeight + 4;
|
|
||||||
myGLTexRectInfo =
|
|
||||||
new StaticTextWidget(myTab, font, 10+font.getStringWidth("(*) "), ypos,
|
|
||||||
lwidth, fontHeight, "", kTextAlignLeft);
|
|
||||||
|
|
||||||
// Add items for tab 2
|
// Add items for tab 2
|
||||||
addToFocusList(wid, tabID);
|
addToFocusList(wid, tabID);
|
||||||
|
@ -427,41 +363,6 @@ void VideoDialog::loadConfig()
|
||||||
// Fast loading of Supercharger BIOS
|
// Fast loading of Supercharger BIOS
|
||||||
myFastSCBiosCheckbox->setState(instance().settings().getBool("fastscbios"));
|
myFastSCBiosCheckbox->setState(instance().settings().getBool("fastscbios"));
|
||||||
|
|
||||||
#ifdef DISPLAY_OPENGL
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// TV effects are only enabled in OpenGL mode, and only if GLSL is
|
|
||||||
// available; for now, 'gl_texrect' must also be disabled
|
|
||||||
bool tv = gl && FrameBufferGL::isGLSLAvailable() &&
|
|
||||||
!instance().settings().getBool("gl_texrect");
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// TV color texture effect
|
|
||||||
myTexturePopup->setSelected(instance().settings().getString("tv_tex"), "off");
|
|
||||||
myTexturePopup->setEnabled(tv);
|
|
||||||
|
|
||||||
// TV color bleed effect
|
|
||||||
myBleedPopup->setSelected(instance().settings().getString("tv_bleed"), "off");
|
|
||||||
myBleedPopup->setEnabled(tv);
|
|
||||||
|
|
||||||
// TV random noise effect
|
|
||||||
myNoisePopup->setSelected(instance().settings().getString("tv_noise"), "off");
|
|
||||||
myNoisePopup->setEnabled(tv);
|
|
||||||
|
|
||||||
// TV phosphor burn-off effect
|
|
||||||
myPhosphorCheckbox->setState(instance().settings().getBool("tv_phos"));
|
|
||||||
myPhosphorCheckbox->setEnabled(tv);
|
|
||||||
|
|
||||||
char buf[30];
|
|
||||||
if(gl) sprintf(buf, "OpenGL version detected: %3.1f", FrameBufferGL::glVersion());
|
|
||||||
else sprintf(buf, "OpenGL version detected: None");
|
|
||||||
myGLVersionInfo->setLabel(buf);
|
|
||||||
sprintf(buf, "OpenGL texrect enabled: %s",
|
|
||||||
instance().settings().getBool("gl_texrect") ? "Yes" : "No");
|
|
||||||
myGLTexRectInfo->setLabel(buf);
|
|
||||||
#else
|
|
||||||
myGLVersionInfo->setLabel("OpenGL mode not supported");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
myTab->loadConfig();
|
myTab->loadConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,18 +422,6 @@ void VideoDialog::saveConfig()
|
||||||
// Fast loading of Supercharger BIOS
|
// Fast loading of Supercharger BIOS
|
||||||
instance().settings().setBool("fastscbios", myFastSCBiosCheckbox->getState());
|
instance().settings().setBool("fastscbios", myFastSCBiosCheckbox->getState());
|
||||||
|
|
||||||
// TV color texture effect
|
|
||||||
instance().settings().setString("tv_tex", myTexturePopup->getSelectedTag());
|
|
||||||
|
|
||||||
// TV color bleed effect
|
|
||||||
instance().settings().setString("tv_bleed", myBleedPopup->getSelectedTag());
|
|
||||||
|
|
||||||
// TV image noise effect
|
|
||||||
instance().settings().setString("tv_noise", myNoisePopup->getSelectedTag());
|
|
||||||
|
|
||||||
// TV phosphor burn-off effect
|
|
||||||
instance().settings().setBool("tv_phos", myPhosphorCheckbox->getState());
|
|
||||||
|
|
||||||
// Finally, issue a complete framebuffer re-initialization
|
// Finally, issue a complete framebuffer re-initialization
|
||||||
instance().createFrameBuffer();
|
instance().createFrameBuffer();
|
||||||
}
|
}
|
||||||
|
@ -562,11 +451,6 @@ void VideoDialog::setDefaults()
|
||||||
myCenterCheckbox->setState(false);
|
myCenterCheckbox->setState(false);
|
||||||
myFastSCBiosCheckbox->setState(false);
|
myFastSCBiosCheckbox->setState(false);
|
||||||
|
|
||||||
myTexturePopup->setSelected("off", "");
|
|
||||||
myBleedPopup->setSelected("off", "");
|
|
||||||
myNoisePopup->setSelected("off", "");
|
|
||||||
myPhosphorCheckbox->setState(false);
|
|
||||||
|
|
||||||
// Make sure that mutually-exclusive items are not enabled at the same time
|
// Make sure that mutually-exclusive items are not enabled at the same time
|
||||||
handleFullscreenChange(true);
|
handleFullscreenChange(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,13 +78,7 @@ class VideoDialog : public Dialog
|
||||||
CheckboxWidget* myFastSCBiosCheckbox;
|
CheckboxWidget* myFastSCBiosCheckbox;
|
||||||
|
|
||||||
// TV effects options
|
// TV effects options
|
||||||
PopUpWidget* myTexturePopup;
|
// TODO ...
|
||||||
PopUpWidget* myBleedPopup;
|
|
||||||
PopUpWidget* myNoisePopup;
|
|
||||||
CheckboxWidget* myPhosphorCheckbox;
|
|
||||||
|
|
||||||
StaticTextWidget* myGLVersionInfo;
|
|
||||||
StaticTextWidget* myGLTexRectInfo;
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kNAspectRatioChanged = 'VDan',
|
kNAspectRatioChanged = 'VDan',
|
||||||
|
|
Loading…
Reference in New Issue