mirror of https://github.com/stella-emu/stella.git
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:
parent
ca59c8bd29
commit
7bebe7263d
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 };
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue