OpenGL mode is working again, except it doesn't yet render any text.

Also took the opportunity to clean up the FrameBuffer classes.  There
was a lot of cruddy code there ...


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@387 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2005-03-28 00:04:54 +00:00
parent b5fb1d277d
commit 8d67d0c760
10 changed files with 822 additions and 699 deletions

View File

@ -13,7 +13,7 @@
## See the file "license" for information on usage and redistribution of
## this file, and for a DISCLAIMER OF ALL WARRANTIES.
##
## $Id: makefile,v 1.68 2005-03-27 03:07:33 stephena Exp $
## $Id: makefile,v 1.69 2005-03-28 00:04:49 stephena Exp $
##============================================================================
##============================================================================

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBufferGL.cxx,v 1.14 2005-02-22 18:40:52 stephena Exp $
// $Id: FrameBufferGL.cxx,v 1.15 2005-03-28 00:04:53 stephena Exp $
//============================================================================
#include <SDL.h>
@ -26,6 +26,8 @@
#include "MediaSrc.hxx"
#include "Settings.hxx"
#include "OSystem.hxx"
#include "StellaFont.hxx"
#include "GuiUtils.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBufferGL::FrameBufferGL(OSystem* osystem)
@ -34,7 +36,8 @@ FrameBufferGL::FrameBufferGL(OSystem* osystem)
myScreenmode(0),
myScreenmodeCount(0),
myFilterParam(GL_NEAREST),
myFilterParamName("GL_NEAREST")
myFilterParamName("GL_NEAREST"),
myFSScaleFactor(1.0)
{
}
@ -155,6 +158,12 @@ bool FrameBufferGL::initSubsystem()
<< endl;
}
// Precompute the GUI palette
// We abuse the concept of 'enum' by referring directly to the integer values
for(uInt8 i = 0; i < 5; i++)
for(uInt8 j = 0; j < 3; j++)
myGUIPalette[i][j] = (float)(myGUIColors[i][j]) / 255.0;
return true;
}
@ -167,15 +176,12 @@ bool FrameBufferGL::createScreen()
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, myRGB[3] );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
uInt32 screenWidth = 0;
uInt32 screenHeight = 0;
// Set the screen coordinates
GLdouble orthoWidth = 0.0;
GLdouble orthoHeight = 0.0;
setDimensions(&orthoWidth, &orthoHeight);
// Get the screen coordinates
viewport(&screenWidth, &screenHeight, &orthoWidth, &orthoHeight);
myScreen = SDL_SetVideoMode(screenWidth, screenHeight, 0, mySDLFlags);
myScreen = SDL_SetVideoMode(myScreenDim.w, myScreenDim.h, 0, mySDLFlags);
if(myScreen == NULL)
{
cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl;
@ -184,8 +190,8 @@ bool FrameBufferGL::createScreen()
glPushAttrib(GL_ENABLE_BIT);
// Center the screen horizontally and vertically
glViewport(myDimensions.x, myDimensions.y, myDimensions.w, myDimensions.h);
// Center the image horizontally and vertically
glViewport(myImageDim.x, myImageDim.y, myImageDim.w, myImageDim.h);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
@ -254,58 +260,18 @@ void FrameBufferGL::drawMediaSource()
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, myTexture->pixels);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
uInt32 w = myBaseDim.w, h = myBaseDim.h;
glBegin(GL_QUADS);
glTexCoord2f(myTexCoord[0], myTexCoord[1]); glVertex2i(0, 0);
glTexCoord2f(myTexCoord[2], myTexCoord[1]); glVertex2i(myWidth, 0);
glTexCoord2f(myTexCoord[2], myTexCoord[3]); glVertex2i(myWidth, myHeight);
glTexCoord2f(myTexCoord[0], myTexCoord[3]); glVertex2i(0, myHeight);
glTexCoord2f(myTexCoord[0], myTexCoord[1]); glVertex2i(0, 0);
glTexCoord2f(myTexCoord[2], myTexCoord[1]); glVertex2i(w, 0);
glTexCoord2f(myTexCoord[2], myTexCoord[3]); glVertex2i(w, h);
glTexCoord2f(myTexCoord[0], myTexCoord[3]); glVertex2i(0, h);
glEnd();
// The frame doesn't need to be completely redrawn anymore
theRedrawEntireFrameIndicator = false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::drawBoundedBox(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
{
// First draw the box in the background, alpha-blended
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
glColor4f(0.0, 0.0, 0.0, 0.7);
glRecti(x, y, x+w, y+h);
// Now draw the outer edges
glLineWidth(theZoomLevel);
glColor4f(0.8, 0.8, 0.8, 1.0);
glBegin(GL_LINE_LOOP);
glVertex2i(x, y ); // Top Left
glVertex2i(x+w, y ); // Top Right
glVertex2i(x+w, y+h); // Bottom Right
glVertex2i(x, y+h); // Bottom Left
glEnd();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::drawText(uInt32 x, uInt32 y, const string& message)
{
for(uInt32 i = 0; i < message.length(); i++)
drawChar(x + i*8, y, (uInt32) message[i]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::drawChar(uInt32 x, uInt32 y, uInt32 c)
{
if(c >= 256 )
return;
glBindTexture(GL_TEXTURE_2D, myFontTextureID[c]);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2i(x, y );
glTexCoord2f(1, 0); glVertex2i(x+8, y );
glTexCoord2f(1, 1); glVertex2i(x+8, y+8);
glTexCoord2f(0, 1); glVertex2i(x, y+8);
glEnd();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::preFrameUpdate()
{
@ -323,12 +289,205 @@ void FrameBufferGL::scanline(uInt32 row, uInt8* data)
{
// Invert the row, since OpenGL rows start at the bottom
// of the framebuffer
row = myDimensions.h + myDimensions.y - row - 1;
row = myImageDim.h + myImageDim.y - row - 1;
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(myDimensions.x, row, myDimensions.w, 1, GL_RGB, GL_UNSIGNED_BYTE, data);
glReadPixels(myImageDim.x, row, myImageDim.w, 1, GL_RGB, GL_UNSIGNED_BYTE, data);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::toggleFilter()
{
if(myFilterParam == GL_NEAREST)
{
myFilterParam = GL_LINEAR;
myOSystem->settings().setString("gl_filter", "linear");
showMessage("Filtering: GL_LINEAR");
}
else
{
myFilterParam = GL_NEAREST;
myOSystem->settings().setString("gl_filter", "nearest");
showMessage("Filtering: GL_NEAREST");
}
glBindTexture(GL_TEXTURE_2D, myTextureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myFilterParam);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myFilterParam);
for(uInt32 i = 0; i < 256; i++)
{
glBindTexture(GL_TEXTURE_2D, myFontTextureID[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myFilterParam);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myFilterParam);
}
// The filtering has changed, so redraw the entire screen
theRedrawEntireFrameIndicator = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::hLine(uInt32 x, uInt32 y, uInt32 x2, OverlayColor color)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
glLineWidth(1);
glColor4f(myGUIPalette[color][0],
myGUIPalette[color][1],
myGUIPalette[color][2],
1.0);
glBegin(GL_LINES);
glVertex2i(x, y);
glVertex2i(x2, y);
glEnd();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::vLine(uInt32 x, uInt32 y, uInt32 y2, OverlayColor color)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
glLineWidth(1);
glColor4f(myGUIPalette[color][0],
myGUIPalette[color][1],
myGUIPalette[color][2],
1.0);
glBegin(GL_LINES);
glVertex2i(x, y );
glVertex2i(x, y2);
glEnd();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::blendRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
OverlayColor color, uInt32 level)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
glColor4f(myGUIPalette[color][0],
myGUIPalette[color][1],
myGUIPalette[color][2],
0.7);
glRecti(x, y, x+w, y+h);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
OverlayColor color)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
glColor4f(myGUIPalette[color][0],
myGUIPalette[color][1],
myGUIPalette[color][2],
1.0);
glRecti(x, y, x+w, y+h);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::frameRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
OverlayColor color)
{
cerr << "FrameBufferGL::frameRect()\n";
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::drawChar(uInt8 chr, uInt32 xorig, uInt32 yorig,
OverlayColor color)
{
/*
// If this character is not included in the font, use the default char.
if(chr < myFont->desc().firstchar ||
chr >= myFont->desc().firstchar + myFont->desc().size)
{
if (chr == ' ')
return;
chr = myFont->desc().defaultchar;
}
const Int32 w = myFont->getCharWidth(chr);
const Int32 h = myFont->getFontHeight();
chr -= myFont->desc().firstchar;
const uInt16* tmp = myFont->desc().bits + (myFont->desc().offset ?
myFont->desc().offset[chr] : (chr * h));
SDL_Rect rect;
for(int y = 0; y < h; y++)
{
const uInt16 buffer = *tmp++;
uInt16 mask = 0x8000;
// if(ty + y < 0 || ty + y >= dst->h)
// continue;
for(int x = 0; x < w; x++, mask >>= 1)
{
// if (tx + x < 0 || tx + x >= dst->w)
// continue;
if ((buffer & mask) != 0)
{
rect.x = (x + xorig) * theZoomLevel;
rect.y = (y + yorig) * theZoomLevel;
rect.w = rect.h = theZoomLevel;
SDL_FillRect(myScreen, &rect, myGUIPalette[color]);
}
}
}
*/
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::drawBitmap(uInt32* bitmap, Int32 xorig, Int32 yorig,
OverlayColor color, Int32 h)
{
/*
SDL_Rect rect;
for(int y = 0; y < h; y++)
{
uInt32 mask = 0xF0000000;
// if(ty + y < 0 || ty + y >= _screen.h)
// continue;
for(int x = 0; x < 8; x++, mask >>= 4)
{
// if(tx + x < 0 || tx + x >= _screen.w)
// continue;
if(bitmap[y] & mask)
{
rect.x = (x + xorig) * theZoomLevel;
rect.y = (y + yorig) * theZoomLevel;
rect.w = rect.h = theZoomLevel;
SDL_FillRect(myScreen, &rect, myGUIPalette[color]);
}
}
}
*/
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::translateCoords(Int32* x, Int32* y)
{
// Wow, what a mess :)
*x = (Int32) (((*x - myImageDim.x) / (theZoomLevel * myFSScaleFactor * theAspectRatio)));
*y = (Int32) (((*y - myImageDim.y) / (theZoomLevel * myFSScaleFactor)));
}
/*
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::drawChar(uInt32 x, uInt32 y, uInt32 c)
{
if(c >= 256 )
return;
glBindTexture(GL_TEXTURE_2D, myFontTextureID[c]);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2i(x, y );
glTexCoord2f(1, 0); glVertex2i(x+8, y );
glTexCoord2f(1, 1); glVertex2i(x+8, y+8);
glTexCoord2f(0, 1); glVertex2i(x, y+8);
glEnd();
}
*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferGL::createTextures()
{
@ -338,13 +497,13 @@ bool FrameBufferGL::createTextures()
glDeleteTextures(1, &myTextureID);
glDeleteTextures(256, myFontTextureID);
uInt32 w = power_of_two(myWidth);
uInt32 h = power_of_two(myHeight);
uInt32 w = power_of_two(myBaseDim.w);
uInt32 h = power_of_two(myBaseDim.h);
myTexCoord[0] = 0.0f;
myTexCoord[1] = 0.0f;
myTexCoord[2] = (GLfloat) myWidth / w;
myTexCoord[3] = (GLfloat) myHeight / h;
myTexCoord[2] = (GLfloat) myBaseDim.w / w;
myTexCoord[3] = (GLfloat) myBaseDim.h / h;
myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 16,
0x0000F800, 0x000007E0, 0x0000001F, 0x00000000);
@ -374,6 +533,7 @@ bool FrameBufferGL::createTextures()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
myTexture->pixels);
/*
// Now create the font textures. There are 256 fonts of 8x8 pixels.
// These will be stored in 256 textures of size 8x8.
SDL_Surface* fontTexture = SDL_CreateRGBSurface(SDL_SWSURFACE, 8, 8, 32,
@ -423,6 +583,7 @@ bool FrameBufferGL::createTextures()
}
SDL_FreeSurface(fontTexture);
*/
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
@ -435,150 +596,101 @@ bool FrameBufferGL::createTextures()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::toggleFilter()
void FrameBufferGL::setDimensions(GLdouble* orthoWidth, GLdouble* orthoHeight)
{
if(myFilterParam == GL_NEAREST)
{
myFilterParam = GL_LINEAR;
myOSystem->settings().setString("gl_filter", "linear");
showMessage("Filtering: GL_LINEAR");
}
else
{
myFilterParam = GL_NEAREST;
myOSystem->settings().setString("gl_filter", "nearest");
showMessage("Filtering: GL_NEAREST");
}
// We always know the initial image width and height
// We have to determine final image dimensions as well as screen dimensions
myImageDim.x = 0;
myImageDim.y = 0;
myImageDim.w = (Uint16) (myBaseDim.w * theZoomLevel * theAspectRatio);
myImageDim.h = (Uint16) (myBaseDim.h * theZoomLevel);
myScreenDim = myImageDim;
glBindTexture(GL_TEXTURE_2D, myTextureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myFilterParam);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myFilterParam);
myFSScaleFactor = 1.0f;
for(uInt32 i = 0; i < 256; i++)
{
glBindTexture(GL_TEXTURE_2D, myFontTextureID[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myFilterParam);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myFilterParam);
}
// The filtering has changed, so redraw the entire screen
theRedrawEntireFrameIndicator = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::viewport(uInt32* screenWidth, uInt32* screenHeight,
GLdouble* orthoWidth, GLdouble* orthoHeight)
{
// Determine if we're in fullscreen or windowed mode
// In fullscreen mode, we clip the SDL screen to known resolutions
// In windowed mode, we use the actual image resolution for the SDL screen
if(mySDLFlags & SDL_FULLSCREEN)
{
Uint16 iwidth = (Uint16) (myWidth * theZoomLevel * theAspectRatio);
Uint16 iheight = (Uint16) (myHeight * theZoomLevel);
Uint16 swidth = 0;
Uint16 sheight = 0;
float scaleX = 0.0f;
float scaleY = 0.0f;
float scale = 1.0f;
/* cerr << "original image width = " << iwidth << endl
<< "original image height = " << iheight << endl
<< endl; */
uInt32 desktopWidth = this->screenWidth();
uInt32 desktopHeight = this->screenHeight();
float scaleX = 0.0f;
float scaleY = 0.0f;
if(myOSystem->settings().getBool("gl_fsmax") &&
desktopWidth != 0 && desktopHeight != 0)
myDesktopDim.w != 0 && myDesktopDim.h != 0)
{
// Use the largest available screen size
swidth = desktopWidth;
sheight = desktopHeight;
myScreenDim.w = myDesktopDim.w;
myScreenDim.h = myDesktopDim.h;
scaleX = float(iwidth) / swidth;
scaleY = float(iheight) / sheight;
scaleX = float(myImageDim.w) / myScreenDim.w;
scaleY = float(myImageDim.h) / myScreenDim.h;
// Figure out which dimension is closest to the 10% mark,
// and calculate the scaling required to bring it to exactly 10%
if(scaleX > scaleY)
scale = (swidth * 0.9) / iwidth;
myFSScaleFactor = float(myScreenDim.w * 0.9) / myImageDim.w;
else
scale = (sheight * 0.9) / iheight;
myFSScaleFactor = float(myScreenDim.h * 0.9) / myImageDim.h;
iwidth = (Uint16) (scale * iwidth);
iheight = (Uint16) (scale * iheight);
myImageDim.w = (Uint16) (myFSScaleFactor * myImageDim.w);
myImageDim.h = (Uint16) (myFSScaleFactor * myImageDim.h);
}
else if(myOSystem->settings().getBool("gl_fsmax") &&
myScreenmode != (SDL_Rect**) -1)
{
// Use the largest available screen size
swidth = myScreenmode[0]->w;
sheight = myScreenmode[0]->h;
myScreenDim.w = myScreenmode[0]->w;
myScreenDim.h = myScreenmode[0]->h;
scaleX = float(iwidth) / swidth;
scaleY = float(iheight) / sheight;
scaleX = float(myImageDim.w) / myScreenDim.w;
scaleY = float(myImageDim.h) / myScreenDim.h;
// Figure out which dimension is closest to the 10% mark,
// and calculate the scaling required to bring it to exactly 10%
if(scaleX > scaleY)
scale = (swidth * 0.9) / iwidth;
myFSScaleFactor = (myScreenDim.w * 0.9) / myImageDim.w;
else
scale = (sheight * 0.9) / iheight;
myFSScaleFactor = (myScreenDim.h * 0.9) / myImageDim.h;
iwidth = (Uint16) (scale * iwidth);
iheight = (Uint16) (scale * iheight);
myImageDim.w = (Uint16) (myFSScaleFactor * myImageDim.w);
myImageDim.h = (Uint16) (myFSScaleFactor * myImageDim.h);
}
else if(myScreenmode == (SDL_Rect**) -1)
{
// All modes are available, so use the exact image resolution
swidth = iwidth;
sheight = iheight;
myScreenDim.w = myImageDim.w;
myScreenDim.h = myImageDim.h;
}
else // otherwise, search for a valid screenmode
{
for(uInt32 i = myScreenmodeCount-1; i >= 0; i--)
{
if(iwidth <= myScreenmode[i]->w && iheight <= myScreenmode[i]->h)
if(myImageDim.w <= myScreenmode[i]->w && myImageDim.h <= myScreenmode[i]->h)
{
swidth = myScreenmode[i]->w;
sheight = myScreenmode[i]->h;
myScreenDim.w = myScreenmode[i]->w;
myScreenDim.h = myScreenmode[i]->h;
break;
}
}
}
/* cerr << "image width = " << iwidth << endl
<< "image height = " << iheight << endl
<< "screen width = " << swidth << endl
<< "screen height = " << sheight << endl
<< "scale factor = " << scale << endl
<< endl; */
// Now calculate the OpenGL coordinates
myDimensions.x = (swidth - iwidth) / 2;
myDimensions.y = (sheight - iheight) / 2;
myDimensions.w = iwidth;
myDimensions.h = iheight;
myImageDim.x = (myScreenDim.w - myImageDim.w) / 2;
myImageDim.y = (myScreenDim.h - myImageDim.h) / 2;
*screenWidth = swidth;
*screenHeight = sheight;
*orthoWidth = (GLdouble) (myDimensions.w / (theZoomLevel * theAspectRatio * scale));
*orthoHeight = (GLdouble) (myDimensions.h / (theZoomLevel * scale));
*orthoWidth = (GLdouble) (myImageDim.w / (theZoomLevel * theAspectRatio * myFSScaleFactor));
*orthoHeight = (GLdouble) (myImageDim.h / (theZoomLevel * myFSScaleFactor));
}
else
{
myDimensions.x = 0;
myDimensions.y = 0;
myDimensions.w = (Uint16) (myWidth * theZoomLevel * theAspectRatio);
myDimensions.h = (Uint16) myHeight * theZoomLevel;
*screenWidth = myDimensions.w;
*screenHeight = myDimensions.h;
*orthoWidth = (GLdouble) (myDimensions.w / (theZoomLevel * theAspectRatio));
*orthoHeight = (GLdouble) (myDimensions.h / theZoomLevel);
*orthoWidth = (GLdouble) (myImageDim.w / (theZoomLevel * theAspectRatio));
*orthoHeight = (GLdouble) (myImageDim.h / theZoomLevel);
}
/*
cerr << "myImageDim.x = " << myImageDim.x << ", myImageDim.y = " << myImageDim.y << endl;
cerr << "myImageDim.w = " << myImageDim.w << ", myImageDim.h = " << myImageDim.h << endl;
cerr << "myScreenDim.w = " << myScreenDim.w << ", myScreenDim.h = " << myScreenDim.h << endl;
cerr << endl;
*/
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBufferGL.hxx,v 1.8 2005-02-22 18:40:53 stephena Exp $
// $Id: FrameBufferGL.hxx,v 1.9 2005-03-28 00:04:53 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_GL_HXX
@ -33,7 +33,7 @@ class OSystem;
This class implements an SDL OpenGL framebuffer.
@author Stephen Anthony
@version $Id: FrameBufferGL.hxx,v 1.8 2005-02-22 18:40:53 stephena Exp $
@version $Id: FrameBufferGL.hxx,v 1.9 2005-03-28 00:04:53 stephena Exp $
*/
class FrameBufferGL : public FrameBuffer
{
@ -63,16 +63,6 @@ class FrameBufferGL : public FrameBuffer
*/
virtual bool createScreen();
/**
This routine is called to map a given r,g,b triple to the screen palette.
@param r The red component of the color.
@param g The green component of the color.
@param b The blue component of the color.
*/
virtual Uint32 mapRGB(Uint8 r, Uint8 g, Uint8 b)
{ return SDL_MapRGB(myScreen->format, r, g, b); }
/**
Switches between the two filtering options in OpenGL.
Currently, these are GL_NEAREST and GL_LINEAR.
@ -85,35 +75,6 @@ class FrameBufferGL : public FrameBuffer
*/
virtual void drawMediaSource();
/**
This routine should be called to draw a rectangular box with sides
at the specified coordinates.
@param x The x coordinate
@param y The y coordinate
@param w The width of the box
@param h The height of the box
*/
virtual void drawBoundedBox(uInt32 x, uInt32 y, uInt32 w, uInt32 h);
/**
This routine should be called to draw text at the specified coordinates.
@param x The x coordinate
@param y The y coordinate
@param message The message text
*/
virtual void drawText(uInt32 x, uInt32 y, const string& message);
/**
This routine should be called to draw character 'c' at the specified coordinates.
@param x The x coordinate
@param y The y coordinate
@param c The character to draw
*/
virtual void drawChar(uInt32 x, uInt32 y, uInt32 c);
/**
This routine is called before any drawing is done (per-frame).
*/
@ -132,11 +93,108 @@ class FrameBufferGL : public FrameBuffer
*/
virtual void scanline(uInt32 row, uInt8* data);
/**
This routine is called to map a given r,g,b triple to the screen palette.
@param r The red component of the color.
@param g The green component of the color.
@param b The blue component of the color.
*/
virtual Uint32 mapRGB(Uint8 r, Uint8 g, Uint8 b)
{ return SDL_MapRGB(myScreen->format, r, g, b); }
/**
This routine is called to draw a horizontal line.
@param x The first x coordinate
@param y The y coordinate
@param x2 The second x coordinate
@param color The color of the line
*/
virtual void hLine(uInt32 x, uInt32 y, uInt32 x2, OverlayColor color);
/**
This routine is called to draw a vertical line.
@param x The x coordinate
@param y The first y coordinate
@param y2 The second y coordinate
@param color The color of the line
*/
virtual void vLine(uInt32 x, uInt32 y, uInt32 y2, OverlayColor color);
/**
This routine is called to draw a blended rectangle.
@param x The x coordinate
@param y The y coordinate
@param w The width of the box
@param h The height of the box
@param color FIXME
@param level FIXME
*/
virtual void blendRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
OverlayColor color, uInt32 level = 3);
/**
This routine is called to draw a filled rectangle.
@param x The x coordinate
@param y The y coordinate
@param w The width of the area
@param h The height of the area
@param color The color of the area
*/
virtual void fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
OverlayColor color);
/**
This routine is called to draw a framed rectangle.
@param x The x coordinate
@param y The y coordinate
@param w The width of the area
@param h The height of the area
@param color The color of the surrounding frame
*/
virtual void frameRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
OverlayColor color);
/**
This routine is called to draw the specified character.
@param c The character to draw
@param x The x coordinate
@param y The y coordinate
@param color The color of the character
*/
virtual void drawChar(uInt8 c, uInt32 x, uInt32 y, OverlayColor color);
/**
This routine is called to draw the bitmap image.
@param bitmap The data to draw
@param x The x coordinate
@param y The y coordinate
@param color The color of the character
@param h The height of the data image
*/
virtual void drawBitmap(uInt32* bitmap, Int32 x, Int32 y, OverlayColor color,
Int32 h = 8);
/**
This routine translates the given coordinates to their
unzoomed/unscaled equivalents.
@param x X coordinate to translate
@param y Y coordinate to translate
*/
inline virtual void translateCoords(Int32* x, Int32* y);
private:
bool createTextures();
void viewport(uInt32* screenWidth, uInt32* screenHeight,
GLdouble* orthoWidth, GLdouble* orthoHeight);
void setDimensions(GLdouble* orthoWidth, GLdouble* orthoHeight);
uInt32 power_of_two(uInt32 input)
{
@ -171,11 +229,18 @@ class FrameBufferGL : public FrameBuffer
// The OpenGL font texture handles (one for each character)
GLuint myFontTextureID[256];
// GUI palette
GLfloat myGUIPalette[5][3];
// The texture filtering to use
GLint myFilterParam;
// The name of the texture filtering to use
string myFilterParamName;
// The scaling to use in fullscreen mode
// This is separate from both zoomlevel and aspect ratio
float myFSScaleFactor;
};
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBufferSoft.cxx,v 1.13 2005-03-26 19:26:47 stephena Exp $
// $Id: FrameBufferSoft.cxx,v 1.14 2005-03-28 00:04:53 stephena Exp $
//============================================================================
#include <SDL.h>
@ -84,11 +84,14 @@ bool FrameBufferSoft::initSubsystem()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSoft::createScreen()
{
myDimensions.x = myDimensions.y = 0;
myDimensions.w = myWidth * theZoomLevel;
myDimensions.h = myHeight * theZoomLevel;
myScreenDim.x = myScreenDim.y = 0;
myScreenDim.w = myBaseDim.w * theZoomLevel;
myScreenDim.h = myBaseDim.h * theZoomLevel;
myScreen = SDL_SetVideoMode(myDimensions.w, myDimensions.h, 0, mySDLFlags);
// In software mode, the image and screen dimensions are always the same
myImageDim = myScreenDim;
myScreen = SDL_SetVideoMode(myScreenDim.w, myScreenDim.h, 0, mySDLFlags);
if(myScreen == NULL)
{
cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl;
@ -99,12 +102,6 @@ bool FrameBufferSoft::createScreen()
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSoft::toggleFilter()
{
// No filter added yet ...
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSoft::drawMediaSource()
{
@ -324,6 +321,12 @@ void FrameBufferSoft::scanline(uInt32 row, uInt8* data)
SDL_UnlockSurface(myScreen);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSoft::toggleFilter()
{
// No filter added yet ...
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSoft::hLine(uInt32 x, uInt32 y, uInt32 x2, OverlayColor color)
{
@ -351,8 +354,8 @@ void FrameBufferSoft::vLine(uInt32 x, uInt32 y, uInt32 y2, OverlayColor color)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSoft::blendRect(int x, int y, int w, int h,
OverlayColor color, int level)
void FrameBufferSoft::blendRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
OverlayColor color, uInt32 level)
{
// FIXME - make this do alpha-blending
SDL_Rect tmp;
@ -362,6 +365,7 @@ void FrameBufferSoft::blendRect(int x, int y, int w, int h,
tmp.y = y * theZoomLevel;
tmp.w = w * theZoomLevel;
tmp.h = h * theZoomLevel;
myRectList->add(&tmp);
SDL_FillRect(myScreen, &tmp, myGUIPalette[color]);
}
@ -456,6 +460,15 @@ void FrameBufferSoft::drawBitmap(uInt32* bitmap, Int32 xorig, Int32 yorig,
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSoft::translateCoords(Int32* x, Int32* y)
{
// We don't bother checking offsets or aspect ratios, since
// they're not yet supported in software mode.
*x /= theZoomLevel;
*y /= theZoomLevel;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RectList::RectList(Uint32 size)
{
@ -486,6 +499,9 @@ void RectList::add(SDL_Rect* newRect)
rectArray = temp;
}
//cerr << "RectList::add(): "
// << "x=" << newRect->x << ", y=" << newRect->y << ", w=" << newRect->w << ", h=" << newRect->h << endl;
rectArray[currentRect].x = newRect->x;
rectArray[currentRect].y = newRect->y;
rectArray[currentRect].w = newRect->w;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBufferSoft.hxx,v 1.10 2005-03-26 19:26:47 stephena Exp $
// $Id: FrameBufferSoft.hxx,v 1.11 2005-03-28 00:04:53 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_SOFT_HXX
@ -34,7 +34,7 @@ class RectList;
This class implements an SDL software framebuffer.
@author Stephen Anthony
@version $Id: FrameBufferSoft.hxx,v 1.10 2005-03-26 19:26:47 stephena Exp $
@version $Id: FrameBufferSoft.hxx,v 1.11 2005-03-28 00:04:53 stephena Exp $
*/
class FrameBufferSoft : public FrameBuffer
{
@ -134,8 +134,8 @@ class FrameBufferSoft : public FrameBuffer
@param color FIXME
@param level FIXME
*/
virtual void blendRect(int x, int y, int w, int h,
OverlayColor color, int level = 3);
virtual void blendRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
OverlayColor color, uInt32 level = 3);
/**
This routine is called to draw a filled rectangle.
@ -183,6 +183,15 @@ class FrameBufferSoft : public FrameBuffer
virtual void drawBitmap(uInt32* bitmap, Int32 x, Int32 y, OverlayColor color,
Int32 h = 8);
/**
This routine translates the given coordinates to their
unzoomed/unscaled equivalents.
@param x X coordinate to translate
@param y Y coordinate to translate
*/
inline virtual void translateCoords(Int32* x, Int32* y);
private:
// Used in the dirty update of the SDL surface
RectList* myRectList;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EventHandler.cxx,v 1.38 2005-03-14 04:08:14 stephena Exp $
// $Id: EventHandler.cxx,v 1.39 2005-03-28 00:04:53 stephena Exp $
//============================================================================
#include <algorithm>
@ -194,9 +194,9 @@ void EventHandler::handleMouseMotionEvent(SDL_Event& event)
case S_MENU:
{
// Take window zooming into account
Int32 x = event.motion.x / myOSystem->frameBuffer().zoomLevel();
Int32 y = event.motion.y / myOSystem->frameBuffer().zoomLevel();
Int32 x = event.motion.x, y = event.motion.y;
myOSystem->frameBuffer().translateCoords(&x, &y);
//cerr << "Motion: x = " << x << ", y = " << y << endl;
myOSystem->menu().handleMouseMotionEvent(x, y, 0);
break;
}
@ -232,8 +232,10 @@ void EventHandler::handleMouseButtonEvent(SDL_Event& event, uInt8 state)
case S_MENU:
{
// Take window zooming into account
Int32 x = event.button.x / myOSystem->frameBuffer().zoomLevel();
Int32 y = event.button.y / myOSystem->frameBuffer().zoomLevel();
Int32 x = event.button.x, y = event.button.y;
//if (state) cerr << "B: x = " << x << ", y = " << y << endl;
myOSystem->frameBuffer().translateCoords(&x, &y);
//if (state) cerr << "A: x = " << x << ", y = " << y << endl << endl;
MouseButton button;
if(state == 1)

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBuffer.cxx,v 1.22 2005-03-26 19:26:47 stephena Exp $
// $Id: FrameBuffer.cxx,v 1.23 2005-03-28 00:04:54 stephena Exp $
//============================================================================
#include <sstream>
@ -34,34 +34,13 @@
#include "stella.xpm" // The Stella icon
// Eventually, these may become variables
#define FONTWIDTH 8
#define FONTHEIGHT 8
#define LINEOFFSET 10 // FONTHEIGHT + 1 pixel on top and bottom
#define XBOXOFFSET 8 // 4 pixels to the left and right of text
#define YBOXOFFSET 8 // 4 pixels to the top and bottom of text
#define UPARROW 24 // Indicates more lines above
#define DOWNARROW 25 // Indicates more lines below
#define LEFTARROW 26 // Left arrow for indicating current line
#define RIGHTARROW 27 // Left arrow for indicating current line
#define LEFTMARKER 17 // Indicates item being remapped
#define RIGHTMARKER 16 // Indicates item being remapped
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBuffer::FrameBuffer(OSystem* osystem)
: myOSystem(osystem),
myWidth(0),
myHeight(0),
theRedrawEntireFrameIndicator(true),
myWMAvailable(false),
theZoomLevel(1),
theMaxZoomLevel(1),
theAspectRatio(1.0),
myFrameRate(0),
myPauseStatus(false),
theMenuChangedIndicator(false),
@ -102,6 +81,9 @@ val(0) // FIXME
sizeof(_font_bits)/sizeof(uInt16)
};
myFont = new StellaFont(this, desc);
myBaseDim.x = myBaseDim.y = myBaseDim.w = myBaseDim.h = 0;
myImageDim = myScreenDim = myDesktopDim = myBaseDim;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -116,8 +98,8 @@ void FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height)
{
bool isAlreadyInitialized = (SDL_WasInit(SDL_INIT_VIDEO) & SDL_INIT_VIDEO) > 0;
myWidth = width;
myHeight = height;
myBaseDim.w = (uInt16) width;
myBaseDim.h = (uInt16) height;
myFrameRate = myOSystem->settings().getInt("framerate");
// Now (re)initialize the SDL video system
@ -128,11 +110,31 @@ void FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height)
if(SDL_Init(initflags) < 0)
return;
// Calculate the desktop size
myDesktopDim.w = myDesktopDim.h = 0;
// Get the system-specific WM information
SDL_SysWMinfo myWMInfo;
SDL_VERSION(&myWMInfo.version);
if(SDL_GetWMInfo(&myWMInfo) > 0)
myWMAvailable = true;
{
#if defined(UNIX)
if(myWMInfo.subsystem == SDL_SYSWM_X11)
{
myWMInfo.info.x11.lock_func();
myDesktopDim.w = DisplayWidth(myWMInfo.info.x11.display,
DefaultScreen(myWMInfo.info.x11.display));
myDesktopDim.h = DisplayHeight(myWMInfo.info.x11.display,
DefaultScreen(myWMInfo.info.x11.display));
myWMInfo.info.x11.unlock_func();
}
#elif defined(WIN32)
myDesktopDim.w = (uInt16) GetSystemMetrics(SM_CXSCREEN);
myDesktopDim.h = (uInt16) GetSystemMetrics(SM_CYSCREEN);
#elif defined(MAC_OSX)
// FIXME - add OSX Desktop code here (I don't think SDL supports it yet)
#endif
}
setWindowIcon();
}
@ -146,52 +148,6 @@ void FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height)
// Show or hide the cursor based on the current state
setCursorState();
/*
// Fill the properties info array with game information
ourPropertiesInfo[0] = myConsole->properties().get("Cartridge.Name");
ourPropertiesInfo[1] = "";
ourPropertiesInfo[2] = "Manufacturer: " + myConsole->properties().get("Cartridge.Manufacturer");
ourPropertiesInfo[3] = "Model: " + myConsole->properties().get("Cartridge.ModelNo");
ourPropertiesInfo[4] = "Rarity: " + myConsole->properties().get("Cartridge.Rarity");
ourPropertiesInfo[5] = "Type: " + myConsole->properties().get("Cartridge.Type");
ourPropertiesInfo[6] = "";
ourPropertiesInfo[7] = "MD5SUM:";
ourPropertiesInfo[8] = myConsole->properties().get("Cartridge.MD5");
// Get the arrays containing key and joystick mappings
myConsole->eventHandler().getKeymapArray(&myKeyTable, &myKeyTableSize);
myConsole->eventHandler().getJoymapArray(&myJoyTable, &myJoyTableSize);
// Determine the maximum number of characters that can be onscreen
myMaxColumns = myWidth / FONTWIDTH - 3;
myMaxRows = myHeight / LINEOFFSET - 2;
// Set up the correct bounds for the remap menu
myRemapMenuMaxLines = myRemapMenuItems > myMaxRows ? myMaxRows : myRemapMenuItems;
myRemapMenuLowIndex = 0;
myRemapMenuHighIndex = myRemapMenuMaxLines;
// Figure out the longest properties string,
// and cut any string that is wider than the display
for(uInt8 i = 0; i < 9; i++)
{
if(ourPropertiesInfo[i].length() > (uInt32) myInfoMenuWidth)
{
myInfoMenuWidth = ourPropertiesInfo[i].length();
if(myInfoMenuWidth > myMaxColumns)
{
myInfoMenuWidth = myMaxColumns;
string s = ourPropertiesInfo[i];
ourPropertiesInfo[i] = s.substr(0, myMaxColumns - 3) + "...";
}
}
}
// Finally, load the remap menu with strings,
// clipping any strings which are wider than the display
loadRemapMenu();
*/
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -221,8 +177,8 @@ void FrameBuffer::update()
{
uInt32 w = myFont->getStringWidth(myMessageText) + 10;
uInt32 h = myFont->getFontHeight() + 8;
uInt32 x = (myWidth >> 1) - (w >> 1);
uInt32 y = myHeight - h - LINEOFFSET/2;
uInt32 x = (myBaseDim.w >> 1) - (w >> 1);
uInt32 y = myBaseDim.h - h - 10/2;
// Draw the bounded box and text
blendRect(x+1, y+2, w-2, h-4, kBGColor);
@ -241,7 +197,7 @@ void FrameBuffer::update()
case EventHandler::S_MENU:
{
// Only update the screen if it's been invalidated or the menus have changed
if(theRedrawEntireFrameIndicator)
if(theRedrawEntireFrameIndicator || theMenuChangedIndicator)
{
drawMediaSource();
@ -287,6 +243,284 @@ void FrameBuffer::showMessage(const string& message)
theRedrawEntireFrameIndicator = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::pause(bool status)
{
myPauseStatus = status;
// Now notify the child object, in case it wants to do something
// special when pause is received
//FIXME pauseEvent(myPauseStatus);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setupPalette()
{
// Shade the palette to 75% normal value in pause mode
float shade = 1.0;
if(myPauseStatus)
shade = 0.75;
const uInt32* gamePalette = myOSystem->console().mediaSource().palette();
for(uInt32 i = 0; i < 256; ++i)
{
Uint8 r, g, b;
r = (Uint8) (((gamePalette[i] & 0x00ff0000) >> 16) * shade);
g = (Uint8) (((gamePalette[i] & 0x0000ff00) >> 8) * shade);
b = (Uint8) ((gamePalette[i] & 0x000000ff) * shade);
myPalette[i] = mapRGB(r, g, b);
}
theRedrawEntireFrameIndicator = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::toggleFullscreen(bool given, bool toggle)
{
bool isFullscreen;
if(given)
{
if(myOSystem->settings().getBool("fullscreen") == toggle)
return;
isFullscreen = toggle;
}
else
isFullscreen = !myOSystem->settings().getBool("fullscreen");
// Update the settings
myOSystem->settings().setBool("fullscreen", isFullscreen);
if(isFullscreen)
mySDLFlags |= SDL_FULLSCREEN;
else
mySDLFlags &= ~SDL_FULLSCREEN;
if(!createScreen())
return;
setCursorState();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::resize(Int8 mode, Int8 zoom)
{
// Use the specific zoom level if one is given
// Otherwise use 'mode' to pick the next zoom level
if(zoom != 0)
{
// if(myOSystem->settings().getBool("fullscreen"))
// return;
if(zoom < 1)
theZoomLevel = 1;
else if((uInt32)zoom > theMaxZoomLevel)
theZoomLevel = theMaxZoomLevel;
else
theZoomLevel = zoom;
}
else
{
// reset size to that given in properties
// this is a special case of allowing a resize while in fullscreen mode
if(mode == 0)
{
myScreenDim.w = myBaseDim.w;
myScreenDim.h = myBaseDim.h;
}
else if(mode == 1) // increase size
{
if(myOSystem->settings().getBool("fullscreen"))
return;
if(theZoomLevel == theMaxZoomLevel)
theZoomLevel = 1;
else
theZoomLevel++;
}
else if(mode == -1) // decrease size
{
if(myOSystem->settings().getBool("fullscreen"))
return;
if(theZoomLevel == 1)
theZoomLevel = theMaxZoomLevel;
else
theZoomLevel--;
}
}
if(!createScreen())
return;
// Update the settings
myOSystem->settings().setInt("zoom", theZoomLevel);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setCursorState()
{
bool isFullscreen = myOSystem->settings().getBool("fullscreen");
if(isFullscreen)
grabMouse(true);
switch(myOSystem->eventHandler().state())
{
case EventHandler::S_EMULATE:
if(isFullscreen)
showCursor(false);
else
{
// Keep mouse in game window if grabmouse is selected
grabMouse(myOSystem->settings().getBool("grabmouse"));
// Show or hide the cursor depending on the 'hidecursor' argument
showCursor(!myOSystem->settings().getBool("hidecursor"));
}
break;
default:
showCursor(true);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::showCursor(bool show)
{
if(show)
SDL_ShowCursor(SDL_ENABLE);
else
SDL_ShowCursor(SDL_DISABLE);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::grabMouse(bool grab)
{
if(grab)
SDL_WM_GrabInput(SDL_GRAB_ON);
else
SDL_WM_GrabInput(SDL_GRAB_OFF);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBuffer::fullScreen()
{
return myOSystem->settings().getBool("fullscreen");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameBuffer::maxWindowSizeForScreen()
{
uInt32 sWidth = myDesktopDim.w;
uInt32 sHeight = myDesktopDim.h;
uInt32 multiplier = sWidth / myBaseDim.w;
// If screenwidth or height could not be found, use default zoom value
if(sWidth == 0 || sHeight == 0)
return 4;
bool found = false;
while(!found && (multiplier > 0))
{
// Figure out the desired size of the window
uInt32 width = myBaseDim.w * multiplier;
uInt32 height = myBaseDim.h * multiplier;
if((width < sWidth) && (height < sHeight))
found = true;
else
multiplier--;
}
if(found)
return multiplier;
else
return 1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setWindowTitle(const string& title)
{
SDL_WM_SetCaption(title.c_str(), "stella");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setWindowIcon()
{
#ifndef MAC_OSX
// Set the window icon
uInt32 w, h, ncols, nbytes;
uInt32 rgba[256], icon[32 * 32];
uInt8 mask[32][4];
sscanf(stella_icon[0], "%d %d %d %d", &w, &h, &ncols, &nbytes);
if((w != 32) || (h != 32) || (ncols > 255) || (nbytes > 1))
{
cerr << "ERROR: Couldn't load the icon.\n";
return;
}
for(uInt32 i = 0; i < ncols; i++)
{
unsigned char code;
char color[32];
uInt32 col;
sscanf(stella_icon[1 + i], "%c c %s", &code, color);
if(!strcmp(color, "None"))
col = 0x00000000;
else if(!strcmp(color, "black"))
col = 0xFF000000;
else if (color[0] == '#')
{
sscanf(color + 1, "%06x", &col);
col |= 0xFF000000;
}
else
{
cerr << "ERROR: Couldn't load the icon.\n";
return;
}
rgba[code] = col;
}
memset(mask, 0, sizeof(mask));
for(h = 0; h < 32; h++)
{
const char* line = stella_icon[1 + ncols + h];
for(w = 0; w < 32; w++)
{
icon[w + 32 * h] = rgba[(int)line[w]];
if(rgba[(int)line[w]] & 0xFF000000)
mask[h][w >> 3] |= 1 << (7 - (w & 0x07));
}
}
SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(icon, 32, 32, 32,
32 * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000);
SDL_WM_SetIcon(surface, (unsigned char *) mask);
SDL_FreeSurface(surface);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::box(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
OverlayColor colorA, OverlayColor colorB)
{
hLine(x + 1, y, x + w - 2, colorA);
hLine(x, y + 1, x + w - 1, colorA);
vLine(x, y + 1, y + h - 2, colorA);
vLine(x + 1, y, y + h - 1, colorA);
hLine(x + 1, y + h - 2, x + w - 1, colorB);
hLine(x + 1, y + h - 1, x + w - 2, colorB);
vLine(x + w - 1, y + 1, y + h - 2, colorB);
vLine(x + w - 2, y + 1, y + h - 1, colorB);
}
/*
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::showMenu(bool show)
@ -508,16 +742,6 @@ void FrameBuffer::sendJoyEvent(StellaEvent::JoyStick stick,
}
*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::pause(bool status)
{
myPauseStatus = status;
// Now notify the child object, in case it wants to do something
// special when pause is received
//FIXME pauseEvent(myPauseStatus);
}
/*
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBuffer::Widget FrameBuffer::currentSelectedWidget()
@ -854,320 +1078,3 @@ const char* FrameBuffer::ourEventName[StellaEvent::LastKCODE] = {
"F11", "F12", "F13", "F14", "F15",
};
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setupPalette()
{
// Shade the palette to 75% normal value in pause mode
float shade = 1.0;
if(myPauseStatus)
shade = 0.75;
const uInt32* gamePalette = myOSystem->console().mediaSource().palette();
for(uInt32 i = 0; i < 256; ++i)
{
Uint8 r, g, b;
r = (Uint8) (((gamePalette[i] & 0x00ff0000) >> 16) * shade);
g = (Uint8) (((gamePalette[i] & 0x0000ff00) >> 8) * shade);
b = (Uint8) ((gamePalette[i] & 0x000000ff) * shade);
myPalette[i] = mapRGB(r, g, b);
}
theRedrawEntireFrameIndicator = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::toggleFullscreen(bool given, bool toggle)
{
bool isFullscreen;
if(given)
{
if(myOSystem->settings().getBool("fullscreen") == toggle)
return;
isFullscreen = toggle;
}
else
isFullscreen = !myOSystem->settings().getBool("fullscreen");
// Update the settings
myOSystem->settings().setBool("fullscreen", isFullscreen);
if(isFullscreen)
mySDLFlags |= SDL_FULLSCREEN;
else
mySDLFlags &= ~SDL_FULLSCREEN;
if(!createScreen())
return;
setCursorState();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::resize(Int8 mode, Int8 zoom)
{
// Use the specific zoom level if one is given
// Otherwise use 'mode' to pick the next zoom level
if(zoom != 0)
{
// if(myOSystem->settings().getBool("fullscreen"))
// return;
if(zoom < 1)
theZoomLevel = 1;
else if((uInt32)zoom > theMaxZoomLevel)
theZoomLevel = theMaxZoomLevel;
else
theZoomLevel = zoom;
}
else
{
// reset size to that given in properties
// this is a special case of allowing a resize while in fullscreen mode
if(mode == 0)
{
myWidth = 1;//FIXME myMediaSource->width() << 1;
myHeight = 1;//FIXME myMediaSource->height();
}
else if(mode == 1) // increase size
{
if(myOSystem->settings().getBool("fullscreen"))
return;
if(theZoomLevel == theMaxZoomLevel)
theZoomLevel = 1;
else
theZoomLevel++;
}
else if(mode == -1) // decrease size
{
if(myOSystem->settings().getBool("fullscreen"))
return;
if(theZoomLevel == 1)
theZoomLevel = theMaxZoomLevel;
else
theZoomLevel--;
}
}
if(!createScreen())
return;
// Update the settings
myOSystem->settings().setInt("zoom", theZoomLevel);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setCursorState()
{
bool isFullscreen = myOSystem->settings().getBool("fullscreen");
if(isFullscreen)
grabMouse(true);
switch(myOSystem->eventHandler().state())
{
case EventHandler::S_EMULATE:
if(isFullscreen)
showCursor(false);
else
{
// Keep mouse in game window if grabmouse is selected
grabMouse(myOSystem->settings().getBool("grabmouse"));
// Show or hide the cursor depending on the 'hidecursor' argument
showCursor(!myOSystem->settings().getBool("hidecursor"));
}
break;
default:
showCursor(true);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::showCursor(bool show)
{
if(show)
SDL_ShowCursor(SDL_ENABLE);
else
SDL_ShowCursor(SDL_DISABLE);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::grabMouse(bool grab)
{
if(grab)
SDL_WM_GrabInput(SDL_GRAB_ON);
else
SDL_WM_GrabInput(SDL_GRAB_OFF);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBuffer::fullScreen()
{
return myOSystem->settings().getBool("fullscreen");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameBuffer::maxWindowSizeForScreen()
{
uInt32 sWidth = screenWidth();
uInt32 sHeight = screenHeight();
uInt32 multiplier = sWidth / myWidth;
// If screenwidth or height could not be found, use default zoom value
if(sWidth == 0 || sHeight == 0)
return 4;
bool found = false;
while(!found && (multiplier > 0))
{
// Figure out the desired size of the window
uInt32 width = (uInt32) (myWidth * multiplier * theAspectRatio);
uInt32 height = myHeight * multiplier;
if((width < sWidth) && (height < sHeight))
found = true;
else
multiplier--;
}
if(found)
return multiplier;
else
return 1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameBuffer::screenWidth()
{
uInt32 width = 0;
if(myWMAvailable)
{
#if defined(UNIX)
if(myWMInfo.subsystem == SDL_SYSWM_X11)
{
myWMInfo.info.x11.lock_func();
width = DisplayWidth(myWMInfo.info.x11.display,
DefaultScreen(myWMInfo.info.x11.display));
myWMInfo.info.x11.unlock_func();
}
#elif defined(WIN32)
width = (uInt32) GetSystemMetrics(SM_CXSCREEN);
#elif defined(MAC_OSX)
// FIXME - add OSX Desktop code here (I don't think SDL supports it yet)
#endif
}
return width;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameBuffer::screenHeight()
{
uInt32 height = 0;
if(myWMAvailable)
{
#if defined(UNIX)
if(myWMInfo.subsystem == SDL_SYSWM_X11)
{
myWMInfo.info.x11.lock_func();
height = DisplayHeight(myWMInfo.info.x11.display,
DefaultScreen(myWMInfo.info.x11.display));
myWMInfo.info.x11.unlock_func();
}
#elif defined(WIN32)
height = (uInt32) GetSystemMetrics(SM_CYSCREEN);
#elif defined(MAC_OSX)
// FIXME - add OSX Desktop code here (I don't think SDL supports it yet)
#endif
}
return height;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setWindowTitle(const string& title)
{
SDL_WM_SetCaption(title.c_str(), "stella");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setWindowIcon()
{
#ifndef MAC_OSX
// Set the window icon
uInt32 w, h, ncols, nbytes;
uInt32 rgba[256], icon[32 * 32];
uInt8 mask[32][4];
sscanf(stella_icon[0], "%d %d %d %d", &w, &h, &ncols, &nbytes);
if((w != 32) || (h != 32) || (ncols > 255) || (nbytes > 1))
{
cerr << "ERROR: Couldn't load the icon.\n";
return;
}
for(uInt32 i = 0; i < ncols; i++)
{
unsigned char code;
char color[32];
uInt32 col;
sscanf(stella_icon[1 + i], "%c c %s", &code, color);
if(!strcmp(color, "None"))
col = 0x00000000;
else if(!strcmp(color, "black"))
col = 0xFF000000;
else if (color[0] == '#')
{
sscanf(color + 1, "%06x", &col);
col |= 0xFF000000;
}
else
{
cerr << "ERROR: Couldn't load the icon.\n";
return;
}
rgba[code] = col;
}
memset(mask, 0, sizeof(mask));
for(h = 0; h < 32; h++)
{
const char* line = stella_icon[1 + ncols + h];
for(w = 0; w < 32; w++)
{
icon[w + 32 * h] = rgba[(int)line[w]];
if(rgba[(int)line[w]] & 0xFF000000)
mask[h][w >> 3] |= 1 << (7 - (w & 0x07));
}
}
SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(icon, 32, 32, 32,
32 * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000);
SDL_WM_SetIcon(surface, (unsigned char *) mask);
SDL_FreeSurface(surface);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::box(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
OverlayColor colorA, OverlayColor colorB)
{
hLine(x + 1, y, x + w - 2, colorA);
hLine(x, y + 1, x + w - 1, colorA);
vLine(x, y + 1, y + h - 2, colorA);
vLine(x + 1, y, y + h - 1, colorA);
hLine(x + 1, y + h - 2, x + w - 1, colorB);
hLine(x + 1, y + h - 1, x + w - 2, colorB);
vLine(x + w - 1, y + 1, y + h - 2, colorB);
vLine(x + w - 2, y + 1, y + h - 1, colorB);
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBuffer.hxx,v 1.22 2005-03-26 19:26:47 stephena Exp $
// $Id: FrameBuffer.hxx,v 1.23 2005-03-28 00:04:54 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_HXX
@ -41,7 +41,7 @@ class OSystem;
All GUI elements (ala ScummVM) are drawn here as well.
@author Stephen Anthony
@version $Id: FrameBuffer.hxx,v 1.22 2005-03-26 19:26:47 stephena Exp $
@version $Id: FrameBuffer.hxx,v 1.23 2005-03-28 00:04:54 stephena Exp $
*/
class FrameBuffer
{
@ -87,43 +87,34 @@ class FrameBuffer
void showMessage(const string& message);
/**
Returns the current width of the framebuffer.
Returns the current width of the framebuffer *before* any scaling.
@return The current unscaled width
*/
inline const uInt32 baseWidth() { return myBaseDim.w; }
/**
Returns the current height of the framebuffer *before* any scaling.
@return The current unscaled height
*/
inline const uInt32 baseHeight() { return myBaseDim.h; }
/**
Returns the current width of the framebuffer image.
Note that this will take into account the current scaling (if any).
@return The current width
*/
uInt32 width() { return myWidth; }
// inline const uInt32 imageWidth() { return myImageDim.w; }
/**
Returns the current height of the framebuffer.
Returns the current height of the framebuffer image.
Note that this will take into account the current scaling (if any).
@return The current height
*/
uInt32 height() { return myHeight; }
#if 0
FIXME
/**
This routine is called to get the width of the onscreen image.
*/
uInt32 imageWidth() { return myDimensions.w; }
/**
This routine is called to get the height of the onscreen image.
*/
uInt32 imageHeight() { return myDimensions.h; }
#endif
/**
This routine is called to get the width of the system desktop.
*/
uInt32 screenWidth();
/**
This routine is called to get the height of the system desktop.
*/
uInt32 screenHeight();
// inline const uInt32 imageHeight() { return myImageDim.h; }
/**
Sets the pause status. While pause is selected, the
@ -191,9 +182,14 @@ FIXME
bool fullScreen();
/**
Answers the current zoom level of the SDL window.
Answers the current zoom level of the framebuffer image in the X axis.
*/
inline uInt32 zoomLevel() { return theZoomLevel; }
inline const float zoomLevelX() { return theZoomLevel * theAspectRatio; }
/**
Answers the current zoom level of the framebuffer image in the X axis.
*/
inline const float zoomLevelY() { return (float) theZoomLevel; }
/**
Calculate the maximum window size that the current screen can hold.
@ -315,8 +311,8 @@ FIXME
@param color FIXME
@param level FIXME
*/
virtual void blendRect(int x, int y, int w, int h,
OverlayColor color, int level = 3) = 0;
virtual void blendRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
OverlayColor color, uInt32 level = 3) = 0;
/**
This routine should be called to draw a filled rectangle.
@ -364,6 +360,15 @@ FIXME
virtual void drawBitmap(uInt32* bitmap, Int32 x, Int32 y, OverlayColor color,
Int32 h = 8) = 0;
/**
This routine should be called to translate the given coordinates
to their unzoomed/unscaled equivalents.
@param x X coordinate to translate
@param y Y coordinate to translate
*/
virtual void translateCoords(Int32* x, Int32* y) = 0;
#if 0
FIXME
/**
@ -380,8 +385,20 @@ FIXME
// The parent system for the framebuffer
OSystem* myOSystem;
// Bounds for the window frame
uInt32 myWidth, myHeight;
// Dimensions of the base image, before zooming.
// All external GUI items should refer to these dimensions,
// since this is the *real* size of the image.
// The other sizes are simply scaled versions of these dimensions.
SDL_Rect myBaseDim;
// Dimensions of the actual image, after zooming
SDL_Rect myImageDim;
// Dimensions of the SDL window (not always the same as the image)
SDL_Rect myScreenDim;
// Dimensions of the desktop area
SDL_Rect myDesktopDim;
// Indicates if the entire frame should be redrawn
bool theRedrawEntireFrameIndicator;
@ -398,16 +415,6 @@ FIXME
// Holds the palette for GUI elements
uInt8 myGUIColors[5][3];
// Used to get window-manager specifics
SDL_SysWMinfo myWMInfo;
// Indicates the width/height and origin x/y of the onscreen image
// (these may be different than the screen/window dimensions)
SDL_Rect myDimensions;
// Indicates if the system-specific WM information is available
bool myWMAvailable;
// Indicates the current zoom level of the SDL screen
uInt32 theZoomLevel;
@ -426,6 +433,30 @@ FIXME
*/
void setWindowIcon();
private:
// Indicates the current framerate of the system
uInt32 myFrameRate;
// Indicates the current pause status
bool myPauseStatus;
// Indicates if the menus should be redrawn
bool theMenuChangedIndicator;
// Message timer
Int32 myMessageTime;
// Message text
string myMessageText;
// Number of times menu have been drawn
uInt32 myMenuRedraws;
int val; // FIXME - remove
};
#endif
/*
// Enumeration representing the different types of user interface widgets
enum Widget { W_NONE, MAIN_MENU, REMAP_MENU, INFO_MENU };
@ -461,26 +492,7 @@ FIXME
// scan the mapping arrays and update the remap menu
void loadRemapMenu();
*/
private:
// Indicates the current framerate of the system
uInt32 myFrameRate;
// Indicates the current pause status
bool myPauseStatus;
// Indicates if the menus should be redrawn
bool theMenuChangedIndicator;
// Message timer
Int32 myMessageTime;
// Message text
string myMessageText;
// Number of times menu have been drawn
uInt32 myMenuRedraws;
int val;
/*
// Structure used for main menu items
struct MainMenuItem
@ -549,6 +561,3 @@ int val;
// Holds the number of items in the joytable array
uInt32 myJoyTableSize;
*/
};
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: OptionsDialog.cxx,v 1.7 2005-03-27 03:07:34 stephena Exp $
// $Id: OptionsDialog.cxx,v 1.8 2005-03-28 00:04:54 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -53,8 +53,11 @@ enum {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OptionsDialog::OptionsDialog(OSystem* osystem)
: Dialog(osystem, (osystem->frameBuffer().width() - kMainMenuWidth) / 2,
(osystem->frameBuffer().height() - kMainMenuHeight)/2,
// FIXME - we have to initialize the video system at least once *before*
// creating a new console. For now, just use predefined values.
// Eventually, this subsystem will have to take into account screen size changes
: Dialog(osystem, (osystem->frameBuffer().baseWidth() - kMainMenuWidth) / 2,
(osystem->frameBuffer().baseHeight() - kMainMenuHeight)/2,
kMainMenuWidth, kMainMenuHeight),
myVideoDialog(NULL)
{
@ -69,8 +72,8 @@ OptionsDialog::OptionsDialog(OSystem* osystem)
addBigButton("Help", kHelpCmd, 'H');
// Set some sane values for the dialog boxes
uInt32 fbWidth = osystem->frameBuffer().width();
uInt32 fbHeight = osystem->frameBuffer().height();
uInt16 fbWidth = osystem->frameBuffer().baseWidth();
uInt16 fbHeight = osystem->frameBuffer().baseHeight();
uInt16 x, y, w, h;
// Now create all the dialogs attached to each menu button
@ -107,7 +110,7 @@ OptionsDialog::~OptionsDialog()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OptionsDialog::checkBounds(uInt32 width, uInt32 height,
void OptionsDialog::checkBounds(uInt16 width, uInt16 height,
uInt16* x, uInt16* y, uInt16* w, uInt16* h)
{
if(*w > width) *w = width;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: OptionsDialog.hxx,v 1.3 2005-03-27 03:07:34 stephena Exp $
// $Id: OptionsDialog.hxx,v 1.4 2005-03-28 00:04:54 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -54,7 +54,7 @@ class OptionsDialog : public Dialog
HelpDialog* myHelpDialog;
private:
void checkBounds(uInt32 width, uInt32 height,
void checkBounds(uInt16 width, uInt16 height,
uInt16* x, uInt16* y, uInt16* w, uInt16* h);
};