Some more work on Blargg scanlines; it's still not correct, but closer

than before.

Fixed compile issue for joystick support (thanks to email from D. Church).
Joystick support still isn't tested, so no guarantees it will work.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2857 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2014-02-22 17:31:16 +00:00
parent ca59c8bd29
commit 7bebe7263d
5 changed files with 63 additions and 107 deletions

View File

@ -136,7 +136,7 @@ void EventHandlerSDL2::pollEvent()
handleEvent(Event::Quit, 1); handleEvent(Event::Quit, 1);
break; // SDL_QUIT break; // SDL_QUIT
#if 0 // FIXME #if 0 //FIXSDL
case SDL_ACTIVEEVENT: case SDL_ACTIVEEVENT:
if((event.active.state & SDL_APPACTIVE) && (event.active.gain == 0)) if((event.active.state & SDL_APPACTIVE) && (event.active.gain == 0))
if(myState == S_EMULATE) enterMenuMode(S_MENU); if(myState == S_EMULATE) enterMenuMode(S_MENU);
@ -159,7 +159,7 @@ EventHandlerSDL2::JoystickSDL2::JoystickSDL2(int idx)
stick = SDL_JoystickOpen(idx); stick = SDL_JoystickOpen(idx);
if(stick) if(stick)
{ {
initialize(SDL_JoystickName(idx), SDL_JoystickNumAxes(stick), initialize(SDL_JoystickName(stick), SDL_JoystickNumAxes(stick),
SDL_JoystickNumButtons(stick), SDL_JoystickNumHats(stick)); SDL_JoystickNumButtons(stick), SDL_JoystickNumHats(stick));
} }
} }

View File

@ -19,10 +19,8 @@
#include <cmath> #include <cmath>
#include "Font.hxx"
#include "FrameBufferSDL2.hxx"
#include "TIA.hxx"
#include "NTSCFilter.hxx" #include "NTSCFilter.hxx"
#include "TIA.hxx"
#include "FBSurfaceTIA.hxx" #include "FBSurfaceTIA.hxx"
@ -33,8 +31,7 @@ FBSurfaceTIA::FBSurfaceTIA(FrameBufferSDL2& buffer)
myTexture(NULL), myTexture(NULL),
myScanlines(NULL), myScanlines(NULL),
myScanlinesEnabled(false), myScanlinesEnabled(false),
myScanlineIntensityI(50), myScanlineIntensity(50)
myScanlineIntensityF(0.5)
{ {
// Texture width is set to contain all possible sizes for a TIA image, // Texture width is set to contain all possible sizes for a TIA image,
// including Blargg filtering // including Blargg filtering
@ -47,12 +44,20 @@ FBSurfaceTIA::FBSurfaceTIA(FrameBufferSDL2& buffer)
mySurface = SDL_CreateRGBSurface(0, width, height, mySurface = SDL_CreateRGBSurface(0, width, height,
pf.BitsPerPixel, pf.Rmask, pf.Gmask, pf.Bmask, pf.Amask); pf.BitsPerPixel, pf.Rmask, pf.Gmask, pf.Bmask, pf.Amask);
mySrc.x = mySrc.y = myDst.x = myDst.y = 0; mySrcR.x = mySrcR.y = myDstR.x = myDstR.y = myScanR.x = myScanR.y = 0;
mySrc.w = myDst.w = width; mySrcR.w = myDstR.w = width;
mySrc.h = myDst.h = height; mySrcR.h = myDstR.h = height;
myScanR.w = 1; myScanR.h = 0;
myPitch = mySurface->pitch / pf.BytesPerPixel; myPitch = mySurface->pitch / pf.BytesPerPixel;
// Generate scanline data
for(int i = 0; i < mySurface->h; i+=2)
{
ourScanData[i] = 0x00000000;
ourScanData[i+1] = 0xff000000;
}
// To generate textures // To generate textures
reload(); reload();
} }
@ -69,15 +74,15 @@ FBSurfaceTIA::~FBSurfaceTIA()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::getPos(uInt32& x, uInt32& y) const void FBSurfaceTIA::getPos(uInt32& x, uInt32& y) const
{ {
x = mySrc.x; x = mySrcR.x;
y = mySrc.y; y = mySrcR.y;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::translateCoords(Int32& x, Int32& y) const void FBSurfaceTIA::translateCoords(Int32& x, Int32& y) const
{ {
x = mySrc.x; x = mySrcR.x;
y = mySrc.y; y = mySrcR.y;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -145,12 +150,12 @@ void FBSurfaceTIA::update()
} }
// Draw TIA image // Draw TIA image
SDL_UpdateTexture(myTexture, &mySrc, mySurface->pixels, mySurface->pitch); SDL_UpdateTexture(myTexture, &mySrcR, mySurface->pixels, mySurface->pitch);
SDL_RenderCopy(myFB.myRenderer, myTexture, &mySrc, &myDst); SDL_RenderCopy(myFB.myRenderer, myTexture, &mySrcR, &myDstR);
// Draw overlaying scanlines // Draw overlaying scanlines
if(myScanlinesEnabled) if(myScanlinesEnabled)
SDL_RenderCopy(myFB.myRenderer, myScanlines, NULL, &myDst); SDL_RenderCopy(myFB.myRenderer, myScanlines, &myScanR, &myDstR);
// Let postFrameUpdate() know that a change has been made // Let postFrameUpdate() know that a change has been made
myFB.myDirtyFlag = true; myFB.myDirtyFlag = true;
@ -188,17 +193,16 @@ void FBSurfaceTIA::reload()
// Re-create scanline texture (contents don't change) // Re-create scanline texture (contents don't change)
myScanlines = SDL_CreateTexture(myFB.myRenderer, myScanlines = SDL_CreateTexture(myFB.myRenderer,
SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC,
1, 2); 1, mySurface->h);
SDL_SetTextureBlendMode(myScanlines, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(myScanlines, SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(myScanlines, myScanlineIntensityF*255); SDL_SetTextureAlphaMod(myScanlines, myScanlineIntensity*2.55);
SDL_UpdateTexture(myScanlines, NULL, ourScanData, 1); SDL_UpdateTexture(myScanlines, &myScanR, ourScanData, 4);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::setScanIntensity(uInt32 intensity) void FBSurfaceTIA::setScanIntensity(uInt32 intensity)
{ {
myScanlineIntensityI = intensity; myScanlineIntensity = intensity;
myScanlineIntensityF = intensity / 100.0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -231,9 +235,20 @@ void FBSurfaceTIA::setScanInterpolation(bool enable)
void FBSurfaceTIA::updateCoords(uInt32 baseH, void FBSurfaceTIA::updateCoords(uInt32 baseH,
uInt32 imgX, uInt32 imgY, uInt32 imgW, uInt32 imgH) uInt32 imgX, uInt32 imgY, uInt32 imgW, uInt32 imgH)
{ {
mySrc.h = baseH; mySrcR.h = baseH;
myDst.w = imgW; myDstR.w = imgW;
myDst.h = imgH; myDstR.h = imgH;
// Scanline repeating is sensitive to non-integral vertical resolution,
// so rounding is performed to eliminate it
// This won't be 100% accurate, but non-integral scaling isn't 100%
// accurate anyway
float x = float(imgH) / floor(((float)imgH / baseH) + 0.5);
cerr << "myScanR.h = " << x << endl;
myScanR.w = 1;
myScanR.h = x;
updateCoords(); updateCoords();
} }
@ -242,7 +257,7 @@ void FBSurfaceTIA::updateCoords(uInt32 baseH,
void FBSurfaceTIA::updateCoords() void FBSurfaceTIA::updateCoords()
{ {
// For a TIA surface, only the width can possibly change // For a TIA surface, only the width can possibly change
mySrc.w = myFB.ntscEnabled() ? ATARI_NTSC_OUT_WIDTH(160) : 160; mySrcR.w = myFB.ntscEnabled() ? ATARI_NTSC_OUT_WIDTH(160) : 160;
#if 0 #if 0
// Normal TIA rendering and TV effects use different widths // Normal TIA rendering and TV effects use different widths
@ -326,6 +341,3 @@ void FBSurfaceTIA::setTIAPalette(const uInt32* palette)
{ {
myFB.myNTSCFilter.setTIAPalette(myFB, palette); myFB.myNTSCFilter.setTIAPalette(myFB, palette);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 const FBSurfaceTIA::ourScanData[2] = { 0x00000000, 0xff000000 };

View File

@ -43,8 +43,8 @@ class FBSurfaceTIA : public FBSurface
// only the methods absolutely necessary for dealing with drawing // only the methods absolutely necessary for dealing with drawing
// a TIA image // a TIA image
void getPos(uInt32& x, uInt32& y) const; void getPos(uInt32& x, uInt32& y) const;
uInt32 getWidth() const { return mySrc.w; } uInt32 getWidth() const { return mySrcR.w; }
uInt32 getHeight() const { return mySrc.h; } uInt32 getHeight() const { return mySrcR.h; }
void translateCoords(Int32& x, Int32& y) const; void translateCoords(Int32& x, Int32& y) const;
void update(); void update();
void invalidate(); void invalidate();
@ -68,14 +68,13 @@ class FBSurfaceTIA : public FBSurface
SDL_Surface* mySurface; SDL_Surface* mySurface;
SDL_Texture* myTexture; SDL_Texture* myTexture;
SDL_Texture* myScanlines; SDL_Texture* myScanlines;
SDL_Rect mySrc, myDst; SDL_Rect mySrcR, myDstR, myScanR;
uInt32 myPitch; uInt32 myPitch;
bool myScanlinesEnabled; bool myScanlinesEnabled;
uInt32 myScanlineIntensityI; uInt32 myScanlineIntensity;
float myScanlineIntensityF;
static uInt32 const ourScanData[2]; uInt32 ourScanData[320];
}; };
#endif #endif

View File

@ -88,74 +88,10 @@ FrameBufferSDL2::~FrameBufferSDL2()
bool FrameBufferSDL2::queryHardware(uInt32& w, uInt32& h, ResolutionList& res) bool FrameBufferSDL2::queryHardware(uInt32& w, uInt32& h, ResolutionList& res)
{ {
// First get the maximum windowed desktop resolution // First get the maximum windowed desktop resolution
// Check the 'maxres' setting, which is an undocumented developer feature SDL_DisplayMode desktop;
// that specifies the desktop size SDL_GetDesktopDisplayMode(0, &desktop);
// Normally, this wouldn't be set, and we ask SDL directly w = desktop.w;
const GUI::Size& s = myOSystem->settings().getSize("maxres"); h = desktop.h;
if(s.w <= 0 || s.h <= 0)
{
SDL_DisplayMode desktop;
SDL_GetDesktopDisplayMode(0, &desktop);
w = desktop.w;
h = desktop.h;
}
#if 0
// Various parts of the codebase assume a minimum screen size of 320x240
if(!(myDesktopWidth >= 320 && myDesktopHeight >= 240))
{
logMessage("ERROR: queryVideoHardware failed, "
"window 320x240 or larger required", 0);
return false;
}
// Then get the valid fullscreen modes
// If there are any errors, just use the desktop resolution
ostringstream buf;
SDL_Rect** modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
if((modes == (SDL_Rect**)0) || (modes == (SDL_Rect**)-1))
{
Resolution r;
r.width = myDesktopWidth;
r.height = myDesktopHeight;
buf << r.width << "x" << r.height;
r.name = buf.str();
myResolutions.push_back(r);
}
else
{
// All modes must fit between the lower and upper limits of the desktop
// For 'small' desktop, this means larger than 320x240
// For 'large'/normal desktop, exclude all those less than 640x480
bool largeDesktop = myDesktopWidth >= 640 && myDesktopHeight >= 480;
uInt32 lowerWidth = largeDesktop ? 640 : 320,
lowerHeight = largeDesktop ? 480 : 240;
for(uInt32 i = 0; modes[i]; ++i)
{
if(modes[i]->w >= lowerWidth && modes[i]->w <= myDesktopWidth &&
modes[i]->h >= lowerHeight && modes[i]->h <= myDesktopHeight)
{
Resolution r;
r.width = modes[i]->w;
r.height = modes[i]->h;
buf.str("");
buf << r.width << "x" << r.height;
r.name = buf.str();
myResolutions.insert_at(0, r); // insert in opposite (of descending) order
}
}
// If no modes were valid, use the desktop dimensions
if(myResolutions.size() == 0)
{
Resolution r;
r.width = myDesktopWidth;
r.height = myDesktopHeight;
buf << r.width << "x" << r.height;
r.name = buf.str();
myResolutions.push_back(r);
}
}
#endif
return true; return true;
} }
@ -491,7 +427,7 @@ void FrameBufferSDL2::enableNTSC(bool enable)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameBufferSDL2::enableScanlines(int relative, int absolute) uInt32 FrameBufferSDL2::enableScanlines(int relative, int absolute)
{ {
int intensity = myTiaSurface->myScanlineIntensityI; int intensity = myTiaSurface->myScanlineIntensity;
if(myTiaSurface) if(myTiaSurface)
{ {
if(relative == 0) intensity = absolute; if(relative == 0) intensity = absolute;
@ -559,7 +495,7 @@ string FrameBufferSDL2::effectsInfo() const
break; break;
case kBlarggNormal: case kBlarggNormal:
buf << myNTSCFilter.getPreset() << ", scanlines=" buf << myNTSCFilter.getPreset() << ", scanlines="
<< myTiaSurface->myScanlineIntensityI << "/" << myTiaSurface->myScanlineIntensity << "/"
#if 0 #if 0
<< (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer"); << (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer");
#endif #endif
@ -567,7 +503,7 @@ string FrameBufferSDL2::effectsInfo() const
break; break;
case kBlarggPhosphor: case kBlarggPhosphor:
buf << myNTSCFilter.getPreset() << ", phosphor, scanlines=" buf << myNTSCFilter.getPreset() << ", phosphor, scanlines="
<< myTiaSurface->myScanlineIntensityI << "/" << myTiaSurface->myScanlineIntensity << "/"
#if 0 #if 0
<< (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer"); << (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer");
#endif #endif

View File

@ -82,12 +82,21 @@ bool FrameBuffer::initialize()
if(!queryHardware(myDesktopWidth, myDesktopHeight, myResolutions)) if(!queryHardware(myDesktopWidth, myDesktopHeight, myResolutions))
return false; return false;
// Check the 'maxres' setting, which is an undocumented developer feature
// that specifies the desktop size (not normally set)
const GUI::Size& s = myOSystem->settings().getSize("maxres");
if(s.w > 0 && s.h > 0)
{
myDesktopWidth = s.w;
myDesktopHeight = s.h;
}
// Various parts of the codebase assume a minimum screen size of 320x240 // Various parts of the codebase assume a minimum screen size of 320x240
myDesktopWidth = BSPF_max(myDesktopWidth, 320u); myDesktopWidth = BSPF_max(myDesktopWidth, 320u);
myDesktopHeight = BSPF_max(myDesktopHeight, 240u); myDesktopHeight = BSPF_max(myDesktopHeight, 240u);
if(!(myDesktopWidth >= 320 && myDesktopHeight >= 240)) if(!(myDesktopWidth >= 320 && myDesktopHeight >= 240))
{ {
myOSystem->logMessage("ERROR: queryVideoHardware failed, " myOSystem->logMessage("ERROR: video init failed, "
"window 320x240 or larger required", 0); "window 320x240 or larger required", 0);
return false; return false;
} }