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);
break; // SDL_QUIT
#if 0 // FIXME
#if 0 //FIXSDL
case SDL_ACTIVEEVENT:
if((event.active.state & SDL_APPACTIVE) && (event.active.gain == 0))
if(myState == S_EMULATE) enterMenuMode(S_MENU);
@ -159,7 +159,7 @@ EventHandlerSDL2::JoystickSDL2::JoystickSDL2(int idx)
stick = SDL_JoystickOpen(idx);
if(stick)
{
initialize(SDL_JoystickName(idx), SDL_JoystickNumAxes(stick),
initialize(SDL_JoystickName(stick), SDL_JoystickNumAxes(stick),
SDL_JoystickNumButtons(stick), SDL_JoystickNumHats(stick));
}
}

View File

@ -19,10 +19,8 @@
#include <cmath>
#include "Font.hxx"
#include "FrameBufferSDL2.hxx"
#include "TIA.hxx"
#include "NTSCFilter.hxx"
#include "TIA.hxx"
#include "FBSurfaceTIA.hxx"
@ -33,8 +31,7 @@ FBSurfaceTIA::FBSurfaceTIA(FrameBufferSDL2& buffer)
myTexture(NULL),
myScanlines(NULL),
myScanlinesEnabled(false),
myScanlineIntensityI(50),
myScanlineIntensityF(0.5)
myScanlineIntensity(50)
{
// Texture width is set to contain all possible sizes for a TIA image,
// including Blargg filtering
@ -47,12 +44,20 @@ FBSurfaceTIA::FBSurfaceTIA(FrameBufferSDL2& buffer)
mySurface = SDL_CreateRGBSurface(0, width, height,
pf.BitsPerPixel, pf.Rmask, pf.Gmask, pf.Bmask, pf.Amask);
mySrc.x = mySrc.y = myDst.x = myDst.y = 0;
mySrc.w = myDst.w = width;
mySrc.h = myDst.h = height;
mySrcR.x = mySrcR.y = myDstR.x = myDstR.y = myScanR.x = myScanR.y = 0;
mySrcR.w = myDstR.w = width;
mySrcR.h = myDstR.h = height;
myScanR.w = 1; myScanR.h = 0;
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
reload();
}
@ -69,15 +74,15 @@ FBSurfaceTIA::~FBSurfaceTIA()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::getPos(uInt32& x, uInt32& y) const
{
x = mySrc.x;
y = mySrc.y;
x = mySrcR.x;
y = mySrcR.y;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::translateCoords(Int32& x, Int32& y) const
{
x = mySrc.x;
y = mySrc.y;
x = mySrcR.x;
y = mySrcR.y;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -145,12 +150,12 @@ void FBSurfaceTIA::update()
}
// Draw TIA image
SDL_UpdateTexture(myTexture, &mySrc, mySurface->pixels, mySurface->pitch);
SDL_RenderCopy(myFB.myRenderer, myTexture, &mySrc, &myDst);
SDL_UpdateTexture(myTexture, &mySrcR, mySurface->pixels, mySurface->pitch);
SDL_RenderCopy(myFB.myRenderer, myTexture, &mySrcR, &myDstR);
// Draw overlaying scanlines
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
myFB.myDirtyFlag = true;
@ -188,17 +193,16 @@ void FBSurfaceTIA::reload()
// Re-create scanline texture (contents don't change)
myScanlines = SDL_CreateTexture(myFB.myRenderer,
SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC,
1, 2);
1, mySurface->h);
SDL_SetTextureBlendMode(myScanlines, SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(myScanlines, myScanlineIntensityF*255);
SDL_UpdateTexture(myScanlines, NULL, ourScanData, 1);
SDL_SetTextureAlphaMod(myScanlines, myScanlineIntensity*2.55);
SDL_UpdateTexture(myScanlines, &myScanR, ourScanData, 4);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::setScanIntensity(uInt32 intensity)
{
myScanlineIntensityI = intensity;
myScanlineIntensityF = intensity / 100.0;
myScanlineIntensity = intensity;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -231,9 +235,20 @@ void FBSurfaceTIA::setScanInterpolation(bool enable)
void FBSurfaceTIA::updateCoords(uInt32 baseH,
uInt32 imgX, uInt32 imgY, uInt32 imgW, uInt32 imgH)
{
mySrc.h = baseH;
myDst.w = imgW;
myDst.h = imgH;
mySrcR.h = baseH;
myDstR.w = imgW;
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();
}
@ -242,7 +257,7 @@ void FBSurfaceTIA::updateCoords(uInt32 baseH,
void FBSurfaceTIA::updateCoords()
{
// 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
// Normal TIA rendering and TV effects use different widths
@ -326,6 +341,3 @@ void FBSurfaceTIA::setTIAPalette(const uInt32* 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
// a TIA image
void getPos(uInt32& x, uInt32& y) const;
uInt32 getWidth() const { return mySrc.w; }
uInt32 getHeight() const { return mySrc.h; }
uInt32 getWidth() const { return mySrcR.w; }
uInt32 getHeight() const { return mySrcR.h; }
void translateCoords(Int32& x, Int32& y) const;
void update();
void invalidate();
@ -68,14 +68,13 @@ class FBSurfaceTIA : public FBSurface
SDL_Surface* mySurface;
SDL_Texture* myTexture;
SDL_Texture* myScanlines;
SDL_Rect mySrc, myDst;
SDL_Rect mySrcR, myDstR, myScanR;
uInt32 myPitch;
bool myScanlinesEnabled;
uInt32 myScanlineIntensityI;
float myScanlineIntensityF;
uInt32 myScanlineIntensity;
static uInt32 const ourScanData[2];
uInt32 ourScanData[320];
};
#endif

View File

@ -88,74 +88,10 @@ FrameBufferSDL2::~FrameBufferSDL2()
bool FrameBufferSDL2::queryHardware(uInt32& w, uInt32& h, ResolutionList& res)
{
// First get the maximum windowed desktop resolution
// Check the 'maxres' setting, which is an undocumented developer feature
// that specifies the desktop size
// Normally, this wouldn't be set, and we ask SDL directly
const GUI::Size& s = myOSystem->settings().getSize("maxres");
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
SDL_DisplayMode desktop;
SDL_GetDesktopDisplayMode(0, &desktop);
w = desktop.w;
h = desktop.h;
return true;
}
@ -491,7 +427,7 @@ void FrameBufferSDL2::enableNTSC(bool enable)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameBufferSDL2::enableScanlines(int relative, int absolute)
{
int intensity = myTiaSurface->myScanlineIntensityI;
int intensity = myTiaSurface->myScanlineIntensity;
if(myTiaSurface)
{
if(relative == 0) intensity = absolute;
@ -559,7 +495,7 @@ string FrameBufferSDL2::effectsInfo() const
break;
case kBlarggNormal:
buf << myNTSCFilter.getPreset() << ", scanlines="
<< myTiaSurface->myScanlineIntensityI << "/"
<< myTiaSurface->myScanlineIntensity << "/"
#if 0
<< (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer");
#endif
@ -567,7 +503,7 @@ string FrameBufferSDL2::effectsInfo() const
break;
case kBlarggPhosphor:
buf << myNTSCFilter.getPreset() << ", phosphor, scanlines="
<< myTiaSurface->myScanlineIntensityI << "/"
<< myTiaSurface->myScanlineIntensity << "/"
#if 0
<< (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer");
#endif

View File

@ -82,12 +82,21 @@ bool FrameBuffer::initialize()
if(!queryHardware(myDesktopWidth, myDesktopHeight, myResolutions))
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
myDesktopWidth = BSPF_max(myDesktopWidth, 320u);
myDesktopHeight = BSPF_max(myDesktopHeight, 240u);
if(!(myDesktopWidth >= 320 && myDesktopHeight >= 240))
{
myOSystem->logMessage("ERROR: queryVideoHardware failed, "
myOSystem->logMessage("ERROR: video init failed, "
"window 320x240 or larger required", 0);
return false;
}