Some pretty huge changes right across the board.

Changed pointers to references in c'tor calls, making things a little safer.

Removed FBSurfaceTIA, since it was tied too closely to SDL itself.  Added a
class called TIASurface that is functionally very similar, but is more generic
and accessible by the FrameBuffer directly.  Eventually, this class will take
responsibility for all things related to rendering the TIA image (Blargg TV
effects, phosphor mode, etc).

TIA rendering is currently borked; fixes will follow ...


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2889 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2014-05-12 23:34:25 +00:00
parent d57184a4fc
commit c8b27ec114
39 changed files with 1095 additions and 1217 deletions

View File

@ -21,7 +21,7 @@
#include "EventHandlerSDL2.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandlerSDL2::EventHandlerSDL2(OSystem* osystem)
EventHandlerSDL2::EventHandlerSDL2(OSystem& osystem)
: EventHandler(osystem)
{
}

View File

@ -37,7 +37,7 @@ class EventHandlerSDL2 : public EventHandler
/**
Create a new SDL2 event handler object
*/
EventHandlerSDL2(OSystem* osystem);
EventHandlerSDL2(OSystem& osystem);
/**
Destructor

View File

@ -21,8 +21,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FBSurfaceSDL2::FBSurfaceSDL2(FrameBufferSDL2& buffer, uInt32 width, uInt32 height)
: FBSurface(buffer.myDefPalette),
myFB(buffer),
: myFB(buffer),
mySurface(NULL),
myTexture(NULL),
mySurfaceIsDirty(true),
@ -111,19 +110,6 @@ void FBSurfaceSDL2::setStaticContents(const uInt32* pixels, uInt32 pitch)
reload();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSDL2::setInterpolationAndBlending(
bool smoothScale, bool useBlend, uInt32 blendAlpha)
{
myInterpolate = smoothScale;
myBlendEnabled = useBlend;
myBlendAlpha = uInt8(blendAlpha * 2.55);
// Re-create the texture with the new settings
free();
reload();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FBSurfaceSDL2::width() const
{
@ -236,3 +222,18 @@ void FBSurfaceSDL2::reload()
SDL_SetTextureAlphaMod(myTexture, myBlendAlpha);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSDL2::applyAttributes(bool immediate)
{
myInterpolate = myAttributes.smoothing;
myBlendEnabled = myAttributes.blending;
myBlendAlpha = uInt8(myAttributes.blendalpha * 2.55);
if(immediate)
{
// Re-create the texture with the new settings
free();
reload();
}
}

View File

@ -33,7 +33,6 @@ class FBSurfaceSDL2 : public FBSurface
{
public:
FBSurfaceSDL2(FrameBufferSDL2& buffer, uInt32 width, uInt32 height);
virtual ~FBSurfaceSDL2();
// Most of the surface drawing primitives are implemented in FBSurface;
@ -44,8 +43,6 @@ class FBSurfaceSDL2 : public FBSurface
void addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h);
void setStaticContents(const uInt32* pixels, uInt32 pitch);
void setInterpolationAndBlending(bool smoothScale, bool useBlend,
uInt32 blendAlpha);
uInt32 width() const;
uInt32 height() const;
@ -63,6 +60,9 @@ class FBSurfaceSDL2 : public FBSurface
void free();
void reload();
protected:
void applyAttributes(bool immediate);
private:
FrameBufferSDL2& myFB;

View File

@ -1,237 +0,0 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2014 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#include <cmath>
#include "NTSCFilter.hxx"
#include "TIA.hxx"
#include "FBSurfaceTIA.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FBSurfaceTIA::FBSurfaceTIA(FrameBufferSDL2& buffer)
: FBSurface(buffer.myDefPalette),
myFB(buffer),
mySurface(NULL),
myTexture(NULL),
myScanlines(NULL),
myScanlinesEnabled(false),
myScanlineIntensity(50)
{
// Texture width is set to contain all possible sizes for a TIA image,
// including Blargg filtering
int width = ATARI_NTSC_OUT_WIDTH(160);
int height = 320;
// Create a surface in the same format as the parent GL class
const SDL_PixelFormat* pf = myFB.myPixelFormat;
mySurface = SDL_CreateRGBSurface(0, width, height*2,
pf->BitsPerPixel, pf->Rmask, pf->Gmask, pf->Bmask, pf->Amask);
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
myScanData = new uInt32[mySurface->h];
for(int i = 0; i < mySurface->h; i+=2)
{
myScanData[i] = 0x00000000;
myScanData[i+1] = 0xff000000;
}
// To generate textures
reload();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FBSurfaceTIA::~FBSurfaceTIA()
{
if(mySurface)
SDL_FreeSurface(mySurface);
free();
delete[] myScanData;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::getPos(uInt32& x, uInt32& y) const
{
x = mySrcR.x;
y = mySrcR.y;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::translateCoords(Int32& x, Int32& y) const
{
x = mySrcR.x;
y = mySrcR.y;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::render()
{
// Copy the mediasource framebuffer to the RGB texture
// In hardware rendering mode, it's faster to just assume that the screen
// is dirty and always do an update
uInt8* currentFrame = myTIA->currentFrameBuffer();
uInt8* previousFrame = myTIA->previousFrameBuffer();
uInt32 width = myTIA->width();
uInt32 height = myTIA->height();
uInt32* buffer = (uInt32*) mySurface->pixels;
// TODO - Eventually 'phosphor' won't be a separate mode, and will become
// a post-processing filter by blending several frames.
switch(myFB.myFilterType)
{
case FrameBufferSDL2::kNormal:
{
uInt32 bufofsY = 0;
uInt32 screenofsY = 0;
for(uInt32 y = 0; y < height; ++y)
{
uInt32 pos = screenofsY;
for(uInt32 x = 0; x < width; ++x)
buffer[pos++] = (uInt32) myFB.myDefPalette[currentFrame[bufofsY + x]];
bufofsY += width;
screenofsY += myPitch;
}
break;
}
case FrameBufferSDL2::kPhosphor:
{
uInt32 bufofsY = 0;
uInt32 screenofsY = 0;
for(uInt32 y = 0; y < height; ++y)
{
uInt32 pos = screenofsY;
for(uInt32 x = 0; x < width; ++x)
{
const uInt32 bufofs = bufofsY + x;
buffer[pos++] = (uInt32)
myFB.myAvgPalette[currentFrame[bufofs]][previousFrame[bufofs]];
}
bufofsY += width;
screenofsY += myPitch;
}
break;
}
case FrameBufferSDL2::kBlarggNormal:
{
myFB.myNTSCFilter.blit_single(currentFrame, width, height,
buffer, mySurface->pitch);
break;
}
case FrameBufferSDL2::kBlarggPhosphor:
{
myFB.myNTSCFilter.blit_double(currentFrame, previousFrame, width, height,
buffer, mySurface->pitch);
break;
}
}
// Draw TIA image
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, &myScanR, &myDstR);
// Let postFrameUpdate() know that a change has been made
myFB.myDirtyFlag = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::invalidate()
{
SDL_FillRect(mySurface, NULL, 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::free()
{
if(myTexture)
{
SDL_DestroyTexture(myTexture);
myTexture = NULL;
}
if(myScanlines)
{
SDL_DestroyTexture(myScanlines);
myScanlines = NULL;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::reload()
{
// Re-create texture; the underlying SDL_Surface is fine as-is
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, myTexFilter[0] ? "1" : "0");
myTexture = SDL_CreateTexture(myFB.myRenderer,
myFB.myPixelFormat->format, SDL_TEXTUREACCESS_STREAMING,
mySurface->w, mySurface->h);
// Re-create scanline texture (contents don't change)
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, myTexFilter[1] ? "1" : "0");
myScanlines = SDL_CreateTexture(myFB.myRenderer,
myFB.myPixelFormat->format, SDL_TEXTUREACCESS_STATIC,
1, mySurface->h);
SDL_SetTextureBlendMode(myScanlines, SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(myScanlines, Uint8(myScanlineIntensity*2.55));
SDL_UpdateTexture(myScanlines, &myScanR, myScanData, 4);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::updateCoords(uInt32 baseH,
uInt32 imgX, uInt32 imgY, uInt32 imgW, uInt32 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
myScanR.w = 1;
myScanR.h = int(2 * float(imgH) / floor(((float)imgH / baseH) + 0.5));
updateCoords();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::updateCoords()
{
// Normal TIA rendering and TV effects use different widths
// We use the same buffer, and only pick the width we need
mySrcR.w = myFB.ntscEnabled() ? ATARI_NTSC_OUT_WIDTH(160) : 160;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::setTIAPalette(const uInt32* palette)
{
myFB.myNTSCFilter.setTIAPalette(myFB, palette);
}

View File

@ -1,104 +0,0 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2014 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#ifndef FB_SURFACE_TIA_HXX
#define FB_SURFACE_TIA_HXX
#include "bspf.hxx"
#include "FrameBuffer.hxx"
#include "FrameBufferSDL2.hxx"
/**
A surface suitable for SDL Render2D API and rendering from a TIA source.
It doesn't implement most of the drawing primitives, since it's concerned
with TIA images only. This class extends FrameBuffer::FBSurface.
@author Stephen Anthony
*/
class FBSurfaceTIA : public FBSurface
{
friend class FrameBufferSDL2;
public:
FBSurfaceTIA(FrameBufferSDL2& buffer);
virtual ~FBSurfaceTIA();
// TIA surfaces don't implement most of the drawing primitives,
// only the methods absolutely necessary for dealing with drawing
// a TIA image
void translateCoords(Int32& x, Int32& y) const;
void render();
void invalidate();
void free();
void reload();
void setStaticContents(const uInt32* pixels, uInt32 pitch) { }
void setInterpolationAndBlending(bool smoothScale, bool useBlend,
uInt32 blendAlpha) { }
uInt32 width() const { return 0; }
uInt32 height() const { return 0; }
const GUI::Rect& srcRect() { return GUI::Rect(); }
const GUI::Rect& dstRect() { return GUI::Rect(); }
///////////////////////////////////////////////////////
void getPos(uInt32& x, uInt32& y) const;
uInt32 getWidth() const { return myDstR.w; }
uInt32 getHeight() const { return myDstR.h; }
///////////////////////////////////////////////////////
void setSrcPos(uInt32 x, uInt32 y) { }
void setSrcSize(uInt32 w, uInt32 h) { }
void setDstPos(uInt32 x, uInt32 y) { }
void setDstSize(uInt32 w, uInt32 h) { }
///////////////////////////////////////////////////////
void setPos(uInt32 x, uInt32 y) { }
void setWidth(uInt32 w) { }
void setHeight(uInt32 h) { }
///////////////////////////////////////////////////////
private:
void setTIA(const TIA& tia) { myTIA = &tia; }
void setTIAPalette(const uInt32* palette);
void enableScanlines(bool enable) { myScanlinesEnabled = enable; }
void setScanIntensity(uInt32 intensity) { myScanlineIntensity = intensity; }
void setTexInterpolation(bool enable) { myTexFilter[0] = enable; }
void setScanInterpolation(bool enable) { myTexFilter[1] = enable; }
void updateCoords(uInt32 baseH, uInt32 imgX, uInt32 imgY, uInt32 imgW, uInt32 imgH);
void updateCoords();
private:
FrameBufferSDL2& myFB;
const TIA* myTIA;
SDL_Surface* mySurface;
SDL_Texture* myTexture;
SDL_Texture* myScanlines;
SDL_Rect mySrcR, myDstR, myScanR;
uInt32 myPitch;
bool myScanlinesEnabled;
uInt32* myScanData;
uInt32 myScanlineIntensity;
bool myTexFilter[2];
};
#endif

View File

@ -31,17 +31,14 @@
#include "TIA.hxx"
#include "FBSurfaceSDL2.hxx"
#include "FBSurfaceTIA.hxx"
#include "FrameBufferSDL2.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBufferSDL2::FrameBufferSDL2(OSystem* osystem)
FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem)
: FrameBuffer(osystem),
myFilterType(kNormal),
myWindow(NULL),
myRenderer(NULL),
myWindowFlags(0),
myTiaSurface(NULL),
myDirtyFlag(true),
myDblBufferedFlag(true)
{
@ -50,7 +47,7 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem* osystem)
{
ostringstream buf;
buf << "ERROR: Couldn't initialize SDL: " << SDL_GetError() << endl;
myOSystem->logMessage(buf.str(), 0);
myOSystem.logMessage(buf.str(), 0);
return;
}
@ -76,9 +73,6 @@ FrameBufferSDL2::~FrameBufferSDL2()
SDL_DestroyWindow(myWindow);
myWindow = NULL;
}
// We're taking responsibility for this surface
delete myTiaSurface;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -102,21 +96,12 @@ void FrameBufferSDL2::queryHardware(uInt32& w, uInt32& h, VariantList& renderers
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode,
bool full)
bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
{
// If not initialized by this point, then immediately fail
if(SDL_WasInit(SDL_INIT_VIDEO) == 0)
return false;
bool inTIAMode =
myOSystem->eventHandler().state() != EventHandler::S_LAUNCHER &&
myOSystem->eventHandler().state() != EventHandler::S_DEBUGGER;
// Grab the initial height before it's updated below
// We need it for the creating the TIA surface
uInt32 baseHeight = mode.image.height() / mode.zoom;
// (Re)create window and renderer
if(myRenderer)
{
@ -130,7 +115,7 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode,
}
// Window centering option
int pos = myOSystem->settings().getBool("center")
int pos = myOSystem.settings().getBool("center")
? SDL_WINDOWPOS_CENTERED : SDL_WINDOWPOS_UNDEFINED;
myWindow = SDL_CreateWindow(title.c_str(),
pos, pos, mode.image.width(), mode.image.height(),
@ -138,60 +123,34 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode,
if(myWindow == NULL)
{
string msg = "ERROR: Unable to open SDL window: " + string(SDL_GetError());
myOSystem->logMessage(msg, 0);
myOSystem.logMessage(msg, 0);
return false;
}
// V'synced blits option
Uint32 renderFlags = SDL_RENDERER_ACCELERATED;
if(myOSystem->settings().getBool("vsync"))
if(myOSystem.settings().getBool("vsync"))
renderFlags |= SDL_RENDERER_PRESENTVSYNC;
// Render hint
const string& video = myOSystem->settings().getString("video");
const string& video = myOSystem.settings().getString("video");
if(video != "")
SDL_SetHint(SDL_HINT_RENDER_DRIVER, video.c_str());
myRenderer = SDL_CreateRenderer(myWindow, -1, renderFlags);
if(myWindow == NULL)
{
string msg = "ERROR: Unable to create SDL renderer: " + string(SDL_GetError());
myOSystem->logMessage(msg, 0);
myOSystem.logMessage(msg, 0);
return false;
}
SDL_RendererInfo renderinfo;
if(SDL_GetRendererInfo(myRenderer, &renderinfo) >= 0)
{
myOSystem->settings().setValue("video", renderinfo.name);
myOSystem.settings().setValue("video", renderinfo.name);
// For now, accelerated renderers imply double buffering
// Eventually, SDL may be updated to query this from the render backend
myDblBufferedFlag = renderinfo.flags & SDL_RENDERER_ACCELERATED;
}
// The framebuffer only takes responsibility for TIA surfaces
// Other surfaces (such as the ones used for dialogs) are allocated
// in the Dialog class
if(inTIAMode)
{
// Since we have free hardware stretching, the base TIA surface is created
// only once, and its texture coordinates changed when we want to draw a
// smaller or larger image
if(!myTiaSurface)
myTiaSurface = new FBSurfaceTIA(*this);
myTiaSurface->updateCoords(baseHeight, mode.image.x(), mode.image.y(),
mode.image.width(), mode.image.height());
myTiaSurface->enableScanlines(ntscEnabled());
myTiaSurface->setTexInterpolation(myOSystem->settings().getBool("tia.inter"));
myTiaSurface->setScanIntensity(myOSystem->settings().getInt("tv.scanlines"));
myTiaSurface->setScanInterpolation(myOSystem->settings().getBool("tv.scaninter"));
myTiaSurface->setTIA(myOSystem->console().tia());
}
// Any previously allocated textures currently in use by various UI items
// need to be refreshed as well
// This *must* come after the TIA settings have been updated
resetSurfaces(myTiaSurface);
return true;
}
@ -218,9 +177,8 @@ string FrameBufferSDL2::about() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::invalidate()
{
SDL_RenderClear(myRenderer);
if(myTiaSurface)
myTiaSurface->invalidate();
myDirtyFlag = true;
// SDL_RenderClear(myRenderer);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -240,7 +198,7 @@ void FrameBufferSDL2::enableFullscreen(bool enable)
{
uInt32 flags = enable ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0;
if(SDL_SetWindowFullscreen(myWindow, flags))
myOSystem->settings().setValue("fullscreen", enable);
myOSystem.settings().setValue("fullscreen", enable);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -253,13 +211,6 @@ bool FrameBufferSDL2::fullScreen() const
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::drawTIA(bool fullRedraw)
{
// The TIA surface takes all responsibility for drawing
myTiaSurface->render();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::postFrameUpdate()
{
@ -271,70 +222,6 @@ void FrameBufferSDL2::postFrameUpdate()
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::enablePhosphor(bool enable, int blend)
{
if(myTiaSurface)
{
myUsePhosphor = enable;
myPhosphorBlend = blend;
myFilterType = FilterType(enable ? myFilterType | 0x01 : myFilterType & 0x10);
myRedrawEntireFrame = true;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::enableNTSC(bool enable)
{
if(myTiaSurface)
{
myFilterType = FilterType(enable ? myFilterType | 0x10 : myFilterType & 0x01);
myTiaSurface->updateCoords();
myTiaSurface->enableScanlines(ntscEnabled());
myTiaSurface->setScanIntensity(myOSystem->settings().getInt("tv.scanlines"));
myTiaSurface->setTexInterpolation(myOSystem->settings().getBool("tia.inter"));
myTiaSurface->setScanInterpolation(myOSystem->settings().getBool("tv.scaninter"));
myRedrawEntireFrame = true;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameBufferSDL2::enableScanlines(int relative, int absolute)
{
if(myTiaSurface)
{
int intensity = myTiaSurface->myScanlineIntensity;
if(relative == 0) intensity = absolute;
else intensity += relative;
intensity = BSPF_max(0, intensity);
intensity = BSPF_min(100, intensity);
myTiaSurface->setScanIntensity(intensity);
myRedrawEntireFrame = true;
return intensity;
}
return 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::enableScanlineInterpolation(bool enable)
{
if(myTiaSurface)
{
myTiaSurface->setScanInterpolation(enable);
myRedrawEntireFrame = true;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::setTIAPalette(const uInt32* palette)
{
FrameBuffer::setTIAPalette(palette);
myTiaSurface->setTIAPalette(palette);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FBSurface* FrameBufferSDL2::createSurface(uInt32 w, uInt32 h) const
{
@ -354,29 +241,3 @@ void FrameBufferSDL2::scanline(uInt32 row, uInt8* data) const
p_gl.ReadPixels(image.x(), row, image.width(), 1, GL_RGB, GL_UNSIGNED_BYTE, data);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string FrameBufferSDL2::effectsInfo() const
{
ostringstream buf;
switch(myFilterType)
{
case kNormal:
buf << "Disabled, normal mode";
break;
case kPhosphor:
buf << "Disabled, phosphor mode";
break;
case kBlarggNormal:
buf << myNTSCFilter.getPreset() << ", scanlines="
<< myTiaSurface->myScanlineIntensity << "/"
<< (myTiaSurface->myTexFilter[1] ? "inter" : "nointer");
break;
case kBlarggPhosphor:
buf << myNTSCFilter.getPreset() << ", phosphor, scanlines="
<< myTiaSurface->myScanlineIntensity << "/"
<< (myTiaSurface->myTexFilter[1] ? "inter" : "nointer");
break;
}
return buf.str();
}

View File

@ -24,8 +24,6 @@
class OSystem;
class FBSurfaceSDL2;
class FBSurfaceTIA;
class TIA;
#include "bspf.hxx"
#include "FrameBuffer.hxx"
@ -40,13 +38,12 @@ class TIA;
class FrameBufferSDL2 : public FrameBuffer
{
friend class FBSurfaceSDL2;
friend class FBSurfaceTIA;
public:
/**
Creates a new SDL2 framebuffer
*/
FrameBufferSDL2(OSystem* osystem);
FrameBufferSDL2(OSystem& osystem);
/**
Destructor
@ -72,24 +69,6 @@ class FrameBufferSDL2 : public FrameBuffer
*/
bool fullScreen() const;
/**
Enable/disable phosphor effect.
*/
void enablePhosphor(bool enable, int blend);
/**
Enable/disable NTSC filtering effects.
*/
void enableNTSC(bool enable);
bool ntscEnabled() const { return myFilterType & 0x10; }
/**
Set up the TIA/emulation palette for a screen of any depth > 8.
@param palette The array of colors
*/
void setTIAPalette(const uInt32* palette);
/**
This method is called to retrieve the R/G/B data from the given pixel.
@ -116,11 +95,6 @@ class FrameBufferSDL2 : public FrameBuffer
*/
bool isDoubleBuffered() const { return myDblBufferedFlag; }
/**
This method is called to query the TV effects in use by the FrameBuffer.
*/
string effectsInfo() const;
/**
This method is called to get the specified scanline data.
@ -140,16 +114,14 @@ class FrameBufferSDL2 : public FrameBuffer
void queryHardware(uInt32& w, uInt32& h, VariantList& renderers);
/**
This method is called to change to the given video mode. If the mode
is successfully changed, 'mode' holds the actual dimensions used.
This method is called to change to the given video mode.
@param title The title for the created window
@param mode The video mode to use
@param full Whether this is a fullscreen or windowed mode
@return False on any errors, else true
*/
bool setVideoMode(const string& title, const VideoMode& mode, bool full);
bool setVideoMode(const string& title, const VideoMode& mode);
/**
Enables/disables fullscreen mode.
@ -181,12 +153,6 @@ class FrameBufferSDL2 : public FrameBuffer
*/
void setWindowIcon() { } // Not currently needed on any supported systems
/**
This method should be called anytime the TIA needs to be redrawn
to the screen (full indicating that a full redraw is required).
*/
void drawTIA(bool full);
/**
This method is called to provide information about the FrameBuffer.
*/
@ -197,27 +163,6 @@ class FrameBufferSDL2 : public FrameBuffer
*/
void postFrameUpdate();
/**
Change scanline intensity and interpolation.
@param relative If non-zero, change current intensity by
'relative' amount, otherwise set to 'absolute'
@return New current intensity
*/
uInt32 enableScanlines(int relative, int absolute = 50);
void enableScanlineInterpolation(bool enable);
private:
// Enumeration created such that phosphor off/on is in LSB,
// and Blargg off/on is in MSB
enum FilterType {
kNormal = 0x00,
kPhosphor = 0x01,
kBlarggNormal = 0x10,
kBlarggPhosphor = 0x11
};
FilterType myFilterType;
private:
// The SDL video buffer
SDL_Window* myWindow;
@ -229,10 +174,6 @@ class FrameBufferSDL2 : public FrameBuffer
// it to point to the actual flags used by the SDL_Surface
uInt32 myWindowFlags;
// The lower-most base surface (will always be a TIA surface,
// since Dialog surfaces are allocated by the Dialog class directly).
FBSurfaceTIA* myTiaSurface;
// Used by mapRGB (when palettes are created)
SDL_PixelFormat* myPixelFormat;

View File

@ -156,8 +156,8 @@ string PNGLibrary::saveImage(const string& filename,
buf_ptr += pitch; // add pitch
}
return saveBufferToPNG(out, buffer, width, height,
props, framebuffer.effectsInfo());
return saveBufferToPNG(out, buffer, width, height, props,
framebuffer.tiaSurface().effectsInfo());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -180,7 +180,7 @@ string PNGLibrary::saveImage(const string& filename,
*buf_ptr++ = 0; // first byte of row is filter type
for(uInt32 x = 0; x < width; ++x)
{
uInt32 pixel = framebuffer.tiaPixel(y*width+x);
uInt32 pixel = framebuffer.tiaSurface().pixel(y*width+x);
framebuffer.getRGB(pixel, &r, &g, &b);
*buf_ptr++ = r;
*buf_ptr++ = g;
@ -191,8 +191,8 @@ string PNGLibrary::saveImage(const string& filename,
}
}
return saveBufferToPNG(out, buffer, width << 1, height,
props, framebuffer.effectsInfo());
return saveBufferToPNG(out, buffer, width << 1, height, props,
framebuffer.tiaSurface().effectsInfo());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -40,7 +40,7 @@ class SoundNull : public Sound
Create a new sound object. The init method must be invoked before
using the object.
*/
SoundNull(OSystem* osystem) : Sound(osystem)
SoundNull(OSystem& osystem) : Sound(osystem)
{
myOSystem->logMessage("Sound disabled.\n", 1);
}

View File

@ -33,7 +33,7 @@
#include "SoundSDL2.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SoundSDL2::SoundSDL2(OSystem* osystem)
SoundSDL2::SoundSDL2(OSystem& osystem)
: Sound(osystem),
myIsEnabled(false),
myIsInitializedFlag(false),
@ -43,17 +43,17 @@ SoundSDL2::SoundSDL2(OSystem* osystem)
myIsMuted(true),
myVolume(100)
{
myOSystem->logMessage("SoundSDL2::SoundSDL2 started ...", 2);
myOSystem.logMessage("SoundSDL2::SoundSDL2 started ...", 2);
// The sound system is opened only once per program run, to eliminate
// issues with opening and closing it multiple times
// This fixes a bug most prevalent with ATI video cards in Windows,
// whereby sound stopped working after the first video change
SDL_AudioSpec desired;
desired.freq = myOSystem->settings().getInt("freq");
desired.freq = myOSystem.settings().getInt("freq");
desired.format = AUDIO_S16SYS;
desired.channels = 2;
desired.samples = myOSystem->settings().getInt("fragsize");
desired.samples = myOSystem.settings().getInt("fragsize");
desired.callback = callback;
desired.userdata = (void*)this;
@ -62,7 +62,7 @@ SoundSDL2::SoundSDL2(OSystem* osystem)
{
buf << "WARNING: Couldn't open SDL audio system! " << endl
<< " " << SDL_GetError() << endl;
myOSystem->logMessage(buf.str(), 0);
myOSystem.logMessage(buf.str(), 0);
return;
}
@ -73,7 +73,7 @@ SoundSDL2::SoundSDL2(OSystem* osystem)
buf << "WARNING: Sound device doesn't support realtime audio! Make "
<< "sure a sound" << endl
<< " server isn't running. Audio is disabled." << endl;
myOSystem->logMessage(buf.str(), 0);
myOSystem.logMessage(buf.str(), 0);
SDL_CloseAudio();
return;
@ -87,7 +87,7 @@ SoundSDL2::SoundSDL2(OSystem* osystem)
myIsInitializedFlag = true;
SDL_PauseAudio(1);
myOSystem->logMessage("SoundSDL2::SoundSDL2 initialized", 2);
myOSystem.logMessage("SoundSDL2::SoundSDL2 initialized", 2);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -100,27 +100,27 @@ SoundSDL2::~SoundSDL2()
myIsEnabled = myIsInitializedFlag = false;
}
myOSystem->logMessage("SoundSDL2 destroyed", 2);
myOSystem.logMessage("SoundSDL2 destroyed", 2);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL2::setEnabled(bool state)
{
myOSystem->settings().setValue("sound", state);
myOSystem.settings().setValue("sound", state);
myOSystem->logMessage(state ? "SoundSDL2::setEnabled(true)" :
myOSystem.logMessage(state ? "SoundSDL2::setEnabled(true)" :
"SoundSDL2::setEnabled(false)", 2);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL2::open()
{
myOSystem->logMessage("SoundSDL2::open started ...", 2);
myOSystem.logMessage("SoundSDL2::open started ...", 2);
myIsEnabled = false;
mute(true);
if(!myIsInitializedFlag || !myOSystem->settings().getBool("sound"))
if(!myIsInitializedFlag || !myOSystem.settings().getBool("sound"))
{
myOSystem->logMessage("Sound disabled\n", 1);
myOSystem.logMessage("Sound disabled\n", 1);
return;
}
@ -130,7 +130,7 @@ void SoundSDL2::open()
myTIASound.channels(myHardwareSpec.channels, myNumChannels == 2);
// Adjust volume to that defined in settings
myVolume = myOSystem->settings().getInt("volume");
myVolume = myOSystem.settings().getInt("volume");
setVolume(myVolume);
// Show some info
@ -142,13 +142,13 @@ void SoundSDL2::open()
<< " Channels: " << (int)myHardwareSpec.channels
<< " (" << chanResult << ")" << endl
<< endl;
myOSystem->logMessage(buf.str(), 1);
myOSystem.logMessage(buf.str(), 1);
// And start the SDL sound subsystem ...
myIsEnabled = true;
mute(false);
myOSystem->logMessage("SoundSDL2::open finished", 2);
myOSystem.logMessage("SoundSDL2::open finished", 2);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -161,7 +161,7 @@ void SoundSDL2::close()
myLastRegisterSetCycle = 0;
myTIASound.reset();
myRegWriteQueue.clear();
myOSystem->logMessage("SoundSDL2::close", 2);
myOSystem.logMessage("SoundSDL2::close", 2);
}
}
@ -193,7 +193,7 @@ void SoundSDL2::setVolume(Int32 percent)
{
if(myIsInitializedFlag && (percent >= 0) && (percent <= 100))
{
myOSystem->settings().setValue("volume", percent);
myOSystem.settings().setValue("volume", percent);
SDL_LockAudio();
myVolume = percent;
myTIASound.volume(percent);
@ -224,7 +224,7 @@ void SoundSDL2::adjustVolume(Int8 direction)
message = "Volume set to ";
message += strval.str();
myOSystem->frameBuffer().showMessage(message);
myOSystem.frameBuffer().showMessage(message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -400,7 +400,7 @@ bool SoundSDL2::save(Serializer& out) const
}
catch(...)
{
myOSystem->logMessage("ERROR: SoundSDL2::save", 0);
myOSystem.logMessage("ERROR: SoundSDL2::save", 0);
return false;
}
@ -441,7 +441,7 @@ bool SoundSDL2::load(Serializer& in)
}
catch(...)
{
myOSystem->logMessage("ERROR: SoundSDL2::load", 0);
myOSystem.logMessage("ERROR: SoundSDL2::load", 0);
return false;
}

View File

@ -43,7 +43,7 @@ class SoundSDL2 : public Sound
Create a new sound object. The init method must be invoked before
using the object.
*/
SoundSDL2(OSystem* osystem);
SoundSDL2(OSystem& osystem);
/**
Destructor

View File

@ -6,7 +6,6 @@ MODULE_OBJS := \
src/common/EventHandlerSDL2.o \
src/common/FrameBufferSDL2.o \
src/common/FBSurfaceSDL2.o \
src/common/FBSurfaceTIA.o \
src/common/SoundSDL2.o \
src/common/FSNodeZIP.o \
src/common/PNGLibrary.o \

View File

@ -17,7 +17,7 @@
// $Id$
//============================================================================
#include "FrameBuffer.hxx"
#include "TIASurface.hxx"
#include "Settings.hxx"
#include "NTSCFilter.hxx"
@ -36,7 +36,7 @@ NTSCFilter::~NTSCFilter()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void NTSCFilter::setTIAPalette(const FrameBuffer& fb, const uInt32* palette)
void NTSCFilter::setTIAPalette(const TIASurface& tiaSurface, const uInt32* palette)
{
// Normal TIA palette contains 256 colours, where every odd indexed colour
// is used for PAL colour-loss effect
@ -58,9 +58,9 @@ void NTSCFilter::setTIAPalette(const FrameBuffer& fb, const uInt32* palette)
uInt8 gj = (palette[j] >> 8) & 0xff;
uInt8 bj = palette[j] & 0xff;
*ptr++ = fb.getPhosphor(ri, rj);
*ptr++ = fb.getPhosphor(gi, gj);
*ptr++ = fb.getPhosphor(bi, bj);
*ptr++ = tiaSurface.getPhosphor(ri, rj);
*ptr++ = tiaSurface.getPhosphor(gi, gj);
*ptr++ = tiaSurface.getPhosphor(bi, bj);
}
}
// Set palette for normal fill

View File

@ -20,7 +20,7 @@
#ifndef NTSC_FILTER_HXX
#define NTSC_FILTER_HXX
class FrameBuffer;
class TIASurface;
class Settings;
#include "bspf.hxx"
@ -67,7 +67,7 @@ class NTSCFilter
uses this as a baseline for calculating its own internal palette
in YIQ format.
*/
void setTIAPalette(const FrameBuffer& fb, const uInt32* palette);
void setTIAPalette(const TIASurface& tiaSurface, const uInt32* palette);
// The following are meant to be used strictly for toggling from the GUI
string setPreset(Preset preset);

View File

@ -28,6 +28,7 @@
#include "Debugger.hxx"
#include "DebuggerParser.hxx"
#include "TIADebug.hxx"
#include "TIASurface.hxx"
#include "TIA.hxx"
#include "TiaOutputWidget.hxx"
@ -150,7 +151,7 @@ void TiaOutputWidget::renderToSurface(FBSurface& s)
for(uInt32 x = 0; x < width; ++x, ++i)
{
uInt8 shift = i > scanoffset ? 1 : 0;
uInt32 pixel = instance().frameBuffer().tiaPixel(i, shift);
uInt32 pixel = instance().frameBuffer().tiaSurface().pixel(i, shift);
*line_ptr++ = pixel;
*line_ptr++ = pixel;
}

View File

@ -66,14 +66,14 @@
#include "Console.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props)
Console::Console(OSystem& osystem, Cartridge& cart, const Properties& props)
: myOSystem(osystem),
myEvent(osystem->eventHandler().event()),
myCart(cart),
myEvent(osystem.eventHandler().event()),
myProperties(props),
myTIA(0),
mySwitches(0),
mySystem(0),
myCart(cart),
myCMHandler(0),
myDisplayFormat(""), // Unknown TV format @ start
myFramerate(0.0), // Unknown framerate @ start
@ -99,27 +99,27 @@ Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props)
myControllers[0] = new Joystick(Controller::Left, myEvent, *mySystem);
myControllers[1] = new Joystick(Controller::Right, myEvent, *mySystem);
M6502* m6502 = new M6502(1, myOSystem->settings());
M6502* m6502 = new M6502(1, myOSystem.settings());
myRiot = new M6532(*this, myOSystem->settings());
myTIA = new TIA(*this, myOSystem->sound(), myOSystem->settings());
myRiot = new M6532(*this, myOSystem.settings());
myTIA = new TIA(*this, myOSystem.sound(), myOSystem.settings());
mySystem->attach(m6502);
mySystem->attach(myRiot);
mySystem->attach(myTIA);
mySystem->attach(myCart);
mySystem->attach(&myCart);
// Auto-detect NTSC/PAL mode if it's requested
string autodetected = "";
myDisplayFormat = myProperties.get(Display_Format);
if(myDisplayFormat == "AUTO" || myOSystem->settings().getBool("rominfo"))
if(myDisplayFormat == "AUTO" || myOSystem.settings().getBool("rominfo"))
{
// Run the TIA, looking for PAL scanline patterns
// We turn off the SuperCharger progress bars, otherwise the SC BIOS
// will take over 250 frames!
// The 'fastscbios' option must be changed before the system is reset
bool fastscbios = myOSystem->settings().getBool("fastscbios");
myOSystem->settings().setValue("fastscbios", true);
bool fastscbios = myOSystem.settings().getBool("fastscbios");
myOSystem.settings().setValue("fastscbios", true);
mySystem->reset(true); // autodetect in reset enabled
for(int i = 0; i < 60; ++i)
myTIA->update();
@ -131,7 +131,7 @@ Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props)
}
// Don't forget to reset the SC progress bars again
myOSystem->settings().setValue("fastscbios", fastscbios);
myOSystem.settings().setValue("fastscbios", fastscbios);
}
myConsoleInfo.DisplayFormat = myDisplayFormat + autodetected;
@ -157,8 +157,8 @@ Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props)
// Other ROMs can use it if the setting is enabled
bool joyallow4 = md5 == "aa1c41f86ec44c0a44eb64c332ce08af" ||
md5 == "1bf503c724001b09be79c515ecfcbd03" ||
myOSystem->settings().getBool("joyallow4");
myOSystem->eventHandler().allowAllDirections(joyallow4);
myOSystem.settings().getBool("joyallow4");
myOSystem.eventHandler().allowAllDirections(joyallow4);
// Reset the system to its power-on state
mySystem->reset();
@ -168,9 +168,9 @@ Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props)
myConsoleInfo.CartMD5 = myProperties.get(Cartridge_MD5);
myConsoleInfo.Control0 = myControllers[0]->about();
myConsoleInfo.Control1 = myControllers[1]->about();
myConsoleInfo.BankSwitch = cart->about();
myConsoleInfo.BankSwitch = myCart.about();
myCart->setRomName(myConsoleInfo.CartName);
myCart.setRomName(myConsoleInfo.CartName);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -274,24 +274,24 @@ void Console::toggleFormat(int direction)
}
myProperties.set(Display_Format, saveformat);
setPalette(myOSystem->settings().getString("palette"));
setPalette(myOSystem.settings().getString("palette"));
setTIAProperties();
myTIA->frameReset();
initializeVideo(); // takes care of refreshing the screen
myOSystem->frameBuffer().showMessage(message);
myOSystem.frameBuffer().showMessage(message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::toggleColorLoss()
{
bool colorloss = !myOSystem->settings().getBool("colorloss");
myOSystem->settings().setValue("colorloss", colorloss);
bool colorloss = !myOSystem.settings().getBool("colorloss");
myOSystem.settings().setValue("colorloss", colorloss);
myTIA->enableColorLoss(colorloss);
string message = string("PAL color-loss ") +
(colorloss ? "enabled" : "disabled");
myOSystem->frameBuffer().showMessage(message);
myOSystem.frameBuffer().showMessage(message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -304,7 +304,7 @@ void Console::toggleColorLoss(bool state)
void Console::togglePalette()
{
string palette, message;
palette = myOSystem->settings().getString("palette");
palette = myOSystem.settings().getString("palette");
if(palette == "standard") // switch to z26
{
@ -337,8 +337,8 @@ void Console::togglePalette()
message = "Standard Stella palette";
}
myOSystem->settings().setValue("palette", palette);
myOSystem->frameBuffer().showMessage(message);
myOSystem.settings().setValue("palette", palette);
myOSystem.frameBuffer().showMessage(message);
setPalette(palette);
}
@ -369,7 +369,7 @@ void Console::setPalette(const string& type)
(myDisplayFormat.compare(0, 5, "SECAM") == 0) ? palettes[paletteNum][2] :
palettes[paletteNum][0];
myOSystem->frameBuffer().setTIAPalette(palette);
myOSystem.frameBuffer().setPalette(palette);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -382,16 +382,16 @@ void Console::togglePhosphor()
{
myProperties.set(Display_Phosphor, "No");
enable = false;
myOSystem->frameBuffer().showMessage("Phosphor effect disabled");
myOSystem.frameBuffer().showMessage("Phosphor effect disabled");
}
else
{
myProperties.set(Display_Phosphor, "Yes");
enable = true;
myOSystem->frameBuffer().showMessage("Phosphor effect enabled");
myOSystem.frameBuffer().showMessage("Phosphor effect enabled");
}
myOSystem->frameBuffer().enablePhosphor(enable, blend);
myOSystem.frameBuffer().tiaSurface().enablePhosphor(enable, blend);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -403,35 +403,30 @@ void Console::setProperties(const Properties& props)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FBInitStatus Console::initializeVideo(bool full)
{
setPalette(myOSystem.settings().getString("palette"));
FBInitStatus fbstatus = kSuccess;
if(full)
{
const string& title = string("Stella ") + STELLA_VERSION +
": \"" + myProperties.get(Cartridge_Name) + "\"";
fbstatus = myOSystem->frameBuffer().createDisplay(title,
fbstatus = myOSystem.frameBuffer().createDisplay(title,
myTIA->width() << 1, myTIA->height());
if(fbstatus != kSuccess)
return fbstatus;
myOSystem->frameBuffer().showFrameStats(myOSystem->settings().getBool("stats"));
setColorLossPalette();
myOSystem.frameBuffer().showFrameStats(myOSystem.settings().getBool("stats"));
generateColorLossPalette();
}
bool enable = myProperties.get(Display_Phosphor) == "YES";
int blend = atoi(myProperties.get(Display_PPBlend).c_str());
myOSystem->frameBuffer().enablePhosphor(enable, blend);
myOSystem->frameBuffer().setNTSC(
(NTSCFilter::Preset)myOSystem->settings().getInt("tv.filter"), false);
setPalette(myOSystem->settings().getString("palette"));
// Set the correct framerate based on the format of the ROM
// This can be overridden by changing the framerate in the
// VideoDialog box or on the commandline, but it can't be saved
// (ie, framerate is now determined based on number of scanlines).
int framerate = myOSystem->settings().getInt("framerate");
int framerate = myOSystem.settings().getInt("framerate");
if(framerate > 0) myFramerate = float(framerate);
myOSystem->setFramerate(myFramerate);
myOSystem.setFramerate(myFramerate);
// Make sure auto-frame calculation is only enabled when necessary
myTIA->enableAutoFrame(framerate <= 0);
@ -445,20 +440,19 @@ void Console::initializeAudio()
// Initialize the sound interface.
// The # of channels can be overridden in the AudioDialog box or on
// the commandline, but it can't be saved.
int framerate = myOSystem->settings().getInt("framerate");
int framerate = myOSystem.settings().getInt("framerate");
if(framerate > 0) myFramerate = float(framerate);
const string& sound = myProperties.get(Cartridge_Sound);
myOSystem->sound().close();
myOSystem->sound().setChannels(sound == "STEREO" ? 2 : 1);
myOSystem->sound().setFrameRate(myFramerate);
myOSystem->sound().open();
myOSystem.sound().close();
myOSystem.sound().setChannels(sound == "STEREO" ? 2 : 1);
myOSystem.sound().setFrameRate(myFramerate);
myOSystem.sound().open();
// Make sure auto-frame calculation is only enabled when necessary
myTIA->enableAutoFrame(framerate <= 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/* Original frying research and code by Fred Quimby.
I've tried the following variations on this code:
- Both OR and Exclusive OR instead of AND. This generally crashes the game
@ -478,6 +472,7 @@ void Console::initializeAudio()
Until someone comes up with a more accurate way to emulate frying, I'm
leaving this as Fred posted it. -- B.
*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::fry() const
{
for (int ZPmem=0; ZPmem<0x100; ZPmem += rand() % 4)
@ -493,7 +488,7 @@ void Console::changeYStart(int direction)
{
if(ystart >= 64)
{
myOSystem->frameBuffer().showMessage("YStart at maximum");
myOSystem.frameBuffer().showMessage("YStart at maximum");
return;
}
ystart++;
@ -502,7 +497,7 @@ void Console::changeYStart(int direction)
{
if(ystart == 0)
{
myOSystem->frameBuffer().showMessage("YStart at minimum");
myOSystem.frameBuffer().showMessage("YStart at minimum");
return;
}
ystart--;
@ -512,11 +507,11 @@ void Console::changeYStart(int direction)
myTIA->setYStart(ystart);
myTIA->frameReset();
myOSystem->frameBuffer().refresh();
myOSystem.frameBuffer().refresh();
ostringstream val;
val << ystart;
myOSystem->frameBuffer().showMessage("YStart " + val.str());
myOSystem.frameBuffer().showMessage("YStart " + val.str());
myProperties.set(Display_YStart, val.str());
}
@ -524,14 +519,14 @@ void Console::changeYStart(int direction)
void Console::changeHeight(int direction)
{
uInt32 height = myTIA->height();
uInt32 dheight = myOSystem->frameBuffer().desktopSize().h;
uInt32 dheight = myOSystem.frameBuffer().desktopSize().h;
if(direction == +1) // increase Height
{
height++;
if(height > 256 || height > dheight)
{
myOSystem->frameBuffer().showMessage("Height at maximum");
myOSystem.frameBuffer().showMessage("Height at maximum");
return;
}
}
@ -540,7 +535,7 @@ void Console::changeHeight(int direction)
height--;
if(height < 210)
{
myOSystem->frameBuffer().showMessage("Height at minimum");
myOSystem.frameBuffer().showMessage("Height at minimum");
return;
}
}
@ -553,7 +548,7 @@ void Console::changeHeight(int direction)
ostringstream val;
val << height;
myOSystem->frameBuffer().showMessage("Height " + val.str());
myOSystem.frameBuffer().showMessage("Height " + val.str());
myProperties.set(Display_Height, val.str());
}
@ -586,7 +581,7 @@ void Console::setTIAProperties()
// Make sure these values fit within the bounds of the desktop
// If not, attempt to center vertically
uInt32 dheight = myOSystem->frameBuffer().desktopSize().h;
uInt32 dheight = myOSystem.frameBuffer().desktopSize().h;
if(height > dheight)
{
ystart += height - dheight;
@ -612,7 +607,7 @@ void Console::setControllers(const string& rommd5)
if(left == "COMPUMATE" || right == "COMPUMATE")
{
delete myCMHandler;
myCMHandler = new CompuMate(*((CartridgeCM*)myCart), myEvent, *mySystem);
myCMHandler = new CompuMate(*((CartridgeCM*)&myCart), myEvent, *mySystem);
myControllers[0] = myCMHandler->leftController();
myControllers[1] = myCMHandler->rightController();
return;
@ -729,14 +724,14 @@ void Console::setControllers(const string& rommd5)
}
else if(right == "ATARIVOX")
{
const string& nvramfile = myOSystem->nvramDir() + "atarivox_eeprom.dat";
const string& nvramfile = myOSystem.nvramDir() + "atarivox_eeprom.dat";
myControllers[rightPort] = new AtariVox(Controller::Right, myEvent,
*mySystem, myOSystem->serialPort(),
myOSystem->settings().getString("avoxport"), nvramfile);
*mySystem, myOSystem.serialPort(),
myOSystem.settings().getString("avoxport"), nvramfile);
}
else if(right == "SAVEKEY")
{
const string& nvramfile = myOSystem->nvramDir() + "savekey_eeprom.dat";
const string& nvramfile = myOSystem.nvramDir() + "savekey_eeprom.dat";
myControllers[rightPort] = new SaveKey(Controller::Right, myEvent, *mySystem,
nvramfile);
}
@ -761,7 +756,7 @@ void Console::setControllers(const string& rommd5)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::loadUserPalette()
{
const string& palette = myOSystem->paletteFile();
const string& palette = myOSystem.paletteFile();
ifstream in(palette.c_str(), ios::binary);
if(!in)
return;
@ -816,7 +811,7 @@ void Console::loadUserPalette()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::setColorLossPalette()
void Console::generateColorLossPalette()
{
// Look at all the palettes, since we don't know which one is
// currently active
@ -857,8 +852,8 @@ void Console::setColorLossPalette()
void Console::setFramerate(float framerate)
{
myFramerate = framerate;
myOSystem->setFramerate(framerate);
myOSystem->sound().setFrameRate(framerate);
myOSystem.setFramerate(framerate);
myOSystem.sound().setFrameRate(framerate);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -866,7 +861,7 @@ void Console::toggleTIABit(TIABit bit, const string& bitname, bool show) const
{
bool result = myTIA->toggleBit(bit);
string message = bitname + (result ? " enabled" : " disabled");
myOSystem->frameBuffer().showMessage(message);
myOSystem.frameBuffer().showMessage(message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -874,7 +869,7 @@ void Console::toggleBits() const
{
bool enabled = myTIA->toggleBits();
string message = string("TIA bits") + (enabled ? " enabled" : " disabled");
myOSystem->frameBuffer().showMessage(message);
myOSystem.frameBuffer().showMessage(message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -882,7 +877,7 @@ void Console::toggleTIACollision(TIABit bit, const string& bitname, bool show) c
{
bool result = myTIA->toggleCollision(bit);
string message = bitname + (result ? " collision enabled" : " collision disabled");
myOSystem->frameBuffer().showMessage(message);
myOSystem.frameBuffer().showMessage(message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -890,33 +885,33 @@ void Console::toggleCollisions() const
{
bool enabled = myTIA->toggleCollisions();
string message = string("TIA collisions") + (enabled ? " enabled" : " disabled");
myOSystem->frameBuffer().showMessage(message);
myOSystem.frameBuffer().showMessage(message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::toggleHMOVE() const
{
if(myTIA->toggleHMOVEBlank())
myOSystem->frameBuffer().showMessage("HMOVE blanking enabled");
myOSystem.frameBuffer().showMessage("HMOVE blanking enabled");
else
myOSystem->frameBuffer().showMessage("HMOVE blanking disabled");
myOSystem.frameBuffer().showMessage("HMOVE blanking disabled");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::toggleFixedColors() const
{
if(myTIA->toggleFixedColors())
myOSystem->frameBuffer().showMessage("Fixed debug colors enabled");
myOSystem.frameBuffer().showMessage("Fixed debug colors enabled");
else
myOSystem->frameBuffer().showMessage("Fixed debug colors disabled");
myOSystem.frameBuffer().showMessage("Fixed debug colors disabled");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::addDebugger()
{
#ifdef DEBUGGER_SUPPORT
myOSystem->createDebugger(*this);
mySystem->m6502().attach(myOSystem->debugger());
myOSystem.createDebugger(*this);
mySystem->m6502().attach(myOSystem.debugger());
#endif
}
@ -1156,6 +1151,7 @@ uInt32 Console::ourUserSECAMPalette[256] = { 0 }; // filled from external file
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Console::Console(const Console& console)
: myOSystem(console.myOSystem),
myCart(console.myCart),
myEvent(console.myEvent)
{
assert(false);

View File

@ -68,7 +68,7 @@ class Console : public Serializable
@param cart The cartridge to use with this console
@param props The properties for the cartridge
*/
Console(OSystem* osystem, Cartridge* cart, const Properties& props);
Console(OSystem& osystem, Cartridge& cart, const Properties& props);
/**
Create a new console object by copying another one
@ -126,7 +126,7 @@ class Console : public Serializable
@return The cartridge for this console
*/
Cartridge& cartridge() const { return *myCart; }
Cartridge& cartridge() const { return myCart; }
/**
Get the 6532 used by the console
@ -327,7 +327,7 @@ class Console : public Serializable
normally can't have it enabled (NTSC), since it's also used for
'greying out' the frame in the debugger.
*/
void setColorLossPalette();
void generateColorLossPalette();
/**
Returns a pointer to the palette data for the palette currently defined
@ -339,8 +339,11 @@ class Console : public Serializable
void toggleTIACollision(TIABit bit, const string& bitname, bool show = true) const;
private:
// Pointer to the osystem object
OSystem* myOSystem;
// Reference to the osystem object
OSystem& myOSystem;
// Pointer to the Cartridge (the debugger needs it)
Cartridge& myCart;
// Reference to the event object to use
Event& myEvent;
@ -360,9 +363,6 @@ class Console : public Serializable
// Pointer to the 6502 based system being emulated
System* mySystem;
// Pointer to the Cartridge (the debugger needs it)
Cartridge* myCart;
// Pointer to the 6532 (aka RIOT) (the debugger needs it)
// A RIOT of my own! (...with apologies to The Clash...)
M6532* myRiot;

View File

@ -55,7 +55,7 @@
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandler::EventHandler(OSystem* osystem)
EventHandler::EventHandler(OSystem& osystem)
: myOSystem(osystem),
myOverlay(NULL),
myMouseControl(NULL),
@ -102,27 +102,27 @@ void EventHandler::initialize()
setActionMappings(kEmulationMode);
setActionMappings(kMenuMode);
myUseCtrlKeyFlag = myOSystem->settings().getBool("ctrlcombo");
myUseCtrlKeyFlag = myOSystem.settings().getBool("ctrlcombo");
Joystick::setDeadZone(myOSystem->settings().getInt("joydeadzone"));
Paddles::setDigitalSensitivity(myOSystem->settings().getInt("dsense"));
Paddles::setMouseSensitivity(myOSystem->settings().getInt("msense"));
Joystick::setDeadZone(myOSystem.settings().getInt("joydeadzone"));
Paddles::setDigitalSensitivity(myOSystem.settings().getInt("dsense"));
Paddles::setMouseSensitivity(myOSystem.settings().getInt("msense"));
// Set quick select delay when typing characters in listwidgets
ListWidget::setQuickSelectDelay(myOSystem->settings().getInt("listdelay"));
ListWidget::setQuickSelectDelay(myOSystem.settings().getInt("listdelay"));
// Set number of lines a mousewheel will scroll
ScrollBarWidget::setWheelLines(myOSystem->settings().getInt("mwheel"));
ScrollBarWidget::setWheelLines(myOSystem.settings().getInt("mwheel"));
// Integer to string conversions (for HEX) use upper or lower-case
Common::Base::setHexUppercase(myOSystem->settings().getBool("dbg.uhex"));
Common::Base::setHexUppercase(myOSystem.settings().getBool("dbg.uhex"));
// Joystick stuff
#ifdef JOYSTICK_SUPPORT
initializeJoysticks();
// Map the stelladaptors we've found according to the specified ports
mapStelladaptors(myOSystem->settings().getString("saport"));
mapStelladaptors(myOSystem.settings().getString("saport"));
setJoymap();
setActionMappings(kEmulationMode);
@ -137,9 +137,9 @@ void EventHandler::initialize()
for(uInt32 i = 0; i < myJoysticks.size(); ++i)
buf << " " << i << ": " << myJoysticks[i]->about() << endl;
}
myOSystem->logMessage(buf.str(), 1);
myOSystem.logMessage(buf.str(), 1);
#else
myOSystem->logMessage("Joystick support disabled.", 1);
myOSystem.logMessage("Joystick support disabled.", 1);
#endif
}
@ -147,7 +147,7 @@ void EventHandler::initialize()
void EventHandler::reset(State state)
{
setEventState(state);
myOSystem->state().reset();
myOSystem.state().reset();
setContinuousSnapshots(0);
@ -256,7 +256,7 @@ void EventHandler::mapStelladaptors(const string& saport)
}
}
}
myOSystem->settings().setValue("saport", saport);
myOSystem.settings().setValue("saport", saport);
// We're potentially swapping out an input device behind the back of
// the Event system, so we make sure all Stelladaptor-generated events
@ -276,16 +276,16 @@ void EventHandler::mapStelladaptors(const string& saport)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::toggleSAPortOrder()
{
const string& saport = myOSystem->settings().getString("saport");
const string& saport = myOSystem.settings().getString("saport");
if(saport == "lr")
{
mapStelladaptors("rl");
myOSystem->frameBuffer().showMessage("Stelladaptor ports right/left");
myOSystem.frameBuffer().showMessage("Stelladaptor ports right/left");
}
else
{
mapStelladaptors("lr");
myOSystem->frameBuffer().showMessage("Stelladaptor ports left/right");
myOSystem.frameBuffer().showMessage("Stelladaptor ports left/right");
}
}
@ -299,21 +299,21 @@ void EventHandler::poll(uInt64 time)
// related to emulation
if(myState == S_EMULATE)
{
myOSystem->console().riot().update();
myOSystem.console().riot().update();
#if 0
// Now check if the StateManager should be saving or loading state
// Per-frame cheats are disabled if the StateManager is active, since
// it would interfere with proper playback
if(myOSystem->state().isActive())
if(myOSystem.state().isActive())
{
myOSystem->state().update();
myOSystem.state().update();
}
else
#endif
{
#ifdef CHEATCODE_SUPPORT
const CheatList& cheats = myOSystem->cheat().perFrame();
const CheatList& cheats = myOSystem.cheat().perFrame();
for(uInt32 i = 0; i < cheats.size(); i++)
cheats[i]->evaluate();
#endif
@ -359,7 +359,7 @@ void EventHandler::handleKeyEvent(StellaKey key, StellaMod mod, char ascii, bool
#endif
if(key == KBDK_RETURN)
{
myOSystem->frameBuffer().toggleFullscreen();
myOSystem.frameBuffer().toggleFullscreen();
}
// These only work when in emulation mode
else if(myState == S_EMULATE)
@ -367,160 +367,160 @@ void EventHandler::handleKeyEvent(StellaKey key, StellaMod mod, char ascii, bool
switch(key)
{
case KBDK_EQUALS:
myOSystem->frameBuffer().changeWindowedVidMode(+1);
myOSystem.frameBuffer().changeWindowedVidMode(+1);
break;
case KBDK_MINUS:
myOSystem->frameBuffer().changeWindowedVidMode(-1);
myOSystem.frameBuffer().changeWindowedVidMode(-1);
break;
case KBDK_LEFTBRACKET:
myOSystem->sound().adjustVolume(-1);
myOSystem.sound().adjustVolume(-1);
break;
case KBDK_RIGHTBRACKET:
myOSystem->sound().adjustVolume(+1);
myOSystem.sound().adjustVolume(+1);
break;
case KBDK_PAGEUP: // Alt-PageUp increases YStart
myOSystem->console().changeYStart(+1);
myOSystem.console().changeYStart(+1);
break;
case KBDK_PAGEDOWN: // Alt-PageDown decreases YStart
myOSystem->console().changeYStart(-1);
myOSystem.console().changeYStart(-1);
break;
case KBDK_1: // Alt-1 turns off NTSC filtering
myOSystem->frameBuffer().setNTSC(NTSCFilter::PRESET_OFF);
myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::PRESET_OFF);
break;
case KBDK_2: // Alt-2 turns on 'composite' NTSC filtering
myOSystem->frameBuffer().setNTSC(NTSCFilter::PRESET_COMPOSITE);
myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::PRESET_COMPOSITE);
break;
case KBDK_3: // Alt-3 turns on 'svideo' NTSC filtering
myOSystem->frameBuffer().setNTSC(NTSCFilter::PRESET_SVIDEO);
myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::PRESET_SVIDEO);
break;
case KBDK_4: // Alt-4 turns on 'rgb' NTSC filtering
myOSystem->frameBuffer().setNTSC(NTSCFilter::PRESET_RGB);
myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::PRESET_RGB);
break;
case KBDK_5: // Alt-5 turns on 'bad' NTSC filtering
myOSystem->frameBuffer().setNTSC(NTSCFilter::PRESET_BAD);
myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::PRESET_BAD);
break;
case KBDK_6: // Alt-6 turns on 'custom' NTSC filtering
myOSystem->frameBuffer().setNTSC(NTSCFilter::PRESET_CUSTOM);
myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::PRESET_CUSTOM);
break;
case KBDK_7: // Alt-7 changes scanline intensity for NTSC filtering
if(mod & KMOD_SHIFT)
myOSystem->frameBuffer().setScanlineIntensity(-5);
myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(-5);
else
myOSystem->frameBuffer().setScanlineIntensity(+5);
myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(+5);
break;
case KBDK_8: // Alt-8 turns toggles scanline interpolation
myOSystem->frameBuffer().toggleScanlineInterpolation();
myOSystem.frameBuffer().tiaSurface().toggleScanlineInterpolation();
break;
case KBDK_9: // Alt-9 selects various custom adjustables for NTSC filtering
if(myOSystem->frameBuffer().ntscEnabled())
if(myOSystem.frameBuffer().tiaSurface().ntscEnabled())
{
if(mod & KMOD_SHIFT)
myOSystem->frameBuffer().showMessage(
myOSystem->frameBuffer().ntsc().setPreviousAdjustable());
myOSystem.frameBuffer().showMessage(
myOSystem.frameBuffer().tiaSurface().ntsc().setPreviousAdjustable());
else
myOSystem->frameBuffer().showMessage(
myOSystem->frameBuffer().ntsc().setNextAdjustable());
myOSystem.frameBuffer().showMessage(
myOSystem.frameBuffer().tiaSurface().ntsc().setNextAdjustable());
}
break;
case KBDK_0: // Alt-0 changes custom adjustables for NTSC filtering
if(myOSystem->frameBuffer().ntscEnabled())
if(myOSystem.frameBuffer().tiaSurface().ntscEnabled())
{
if(mod & KMOD_SHIFT)
myOSystem->frameBuffer().showMessage(
myOSystem->frameBuffer().ntsc().decreaseAdjustable());
myOSystem.frameBuffer().showMessage(
myOSystem.frameBuffer().tiaSurface().ntsc().decreaseAdjustable());
else
myOSystem->frameBuffer().showMessage(
myOSystem->frameBuffer().ntsc().increaseAdjustable());
myOSystem.frameBuffer().showMessage(
myOSystem.frameBuffer().tiaSurface().ntsc().increaseAdjustable());
}
break;
case KBDK_Z:
if(mod & KMOD_SHIFT)
myOSystem->console().toggleP0Collision();
myOSystem.console().toggleP0Collision();
else
myOSystem->console().toggleP0Bit();
myOSystem.console().toggleP0Bit();
break;
case KBDK_X:
if(mod & KMOD_SHIFT)
myOSystem->console().toggleP1Collision();
myOSystem.console().toggleP1Collision();
else
myOSystem->console().toggleP1Bit();
myOSystem.console().toggleP1Bit();
break;
case KBDK_C:
if(mod & KMOD_SHIFT)
myOSystem->console().toggleM0Collision();
myOSystem.console().toggleM0Collision();
else
myOSystem->console().toggleM0Bit();
myOSystem.console().toggleM0Bit();
break;
case KBDK_V:
if(mod & KMOD_SHIFT)
myOSystem->console().toggleM1Collision();
myOSystem.console().toggleM1Collision();
else
myOSystem->console().toggleM1Bit();
myOSystem.console().toggleM1Bit();
break;
case KBDK_B:
if(mod & KMOD_SHIFT)
myOSystem->console().toggleBLCollision();
myOSystem.console().toggleBLCollision();
else
myOSystem->console().toggleBLBit();
myOSystem.console().toggleBLBit();
break;
case KBDK_N:
if(mod & KMOD_SHIFT)
myOSystem->console().togglePFCollision();
myOSystem.console().togglePFCollision();
else
myOSystem->console().togglePFBit();
myOSystem.console().togglePFBit();
break;
case KBDK_M:
myOSystem->console().toggleHMOVE();
myOSystem.console().toggleHMOVE();
break;
case KBDK_COMMA:
myOSystem->console().toggleFixedColors();
myOSystem.console().toggleFixedColors();
break;
case KBDK_PERIOD:
if(mod & KMOD_SHIFT)
myOSystem->console().toggleCollisions();
myOSystem.console().toggleCollisions();
else
myOSystem->console().toggleBits();
myOSystem.console().toggleBits();
break;
case KBDK_P: // Alt-p toggles phosphor effect
myOSystem->console().togglePhosphor();
myOSystem.console().togglePhosphor();
break;
case KBDK_L:
myOSystem->frameBuffer().toggleFrameStats();
myOSystem.frameBuffer().toggleFrameStats();
break;
case KBDK_S:
if(myContSnapshotInterval == 0)
{
ostringstream buf;
uInt32 interval = myOSystem->settings().getInt("ssinterval");
uInt32 interval = myOSystem.settings().getInt("ssinterval");
buf << "Enabling shotshots in " << interval << " second intervals";
myOSystem->frameBuffer().showMessage(buf.str());
myOSystem.frameBuffer().showMessage(buf.str());
setContinuousSnapshots(interval);
}
else
@ -529,7 +529,7 @@ void EventHandler::handleKeyEvent(StellaKey key, StellaMod mod, char ascii, bool
buf << "Disabling snapshots, generated "
<< (myContSnapshotCounter / myContSnapshotInterval)
<< " files";
myOSystem->frameBuffer().showMessage(buf.str());
myOSystem.frameBuffer().showMessage(buf.str());
setContinuousSnapshots(0);
}
break;
@ -556,7 +556,7 @@ void EventHandler::handleKeyEvent(StellaKey key, StellaMod mod, char ascii, bool
{
case KBDK_0: // Ctrl-0 switches between mouse control modes
if(myMouseControl)
myOSystem->frameBuffer().showMessage(myMouseControl->next());
myOSystem.frameBuffer().showMessage(myMouseControl->next());
break;
case KBDK_1: // Ctrl-1 swaps Stelladaptor/2600-daptor ports
@ -564,47 +564,47 @@ void EventHandler::handleKeyEvent(StellaKey key, StellaMod mod, char ascii, bool
break;
case KBDK_F: // (Shift) Ctrl-f toggles NTSC/PAL/SECAM mode
myOSystem->console().toggleFormat(mod & KMOD_SHIFT ? -1 : 1);
myOSystem.console().toggleFormat(mod & KMOD_SHIFT ? -1 : 1);
break;
case KBDK_G: // Ctrl-g (un)grabs mouse
if(!myOSystem->frameBuffer().fullScreen())
myOSystem->frameBuffer().toggleGrabMouse();
if(!myOSystem.frameBuffer().fullScreen())
myOSystem.frameBuffer().toggleGrabMouse();
break;
case KBDK_L: // Ctrl-l toggles PAL color-loss effect
myOSystem->console().toggleColorLoss();
myOSystem.console().toggleColorLoss();
break;
case KBDK_P: // Ctrl-p toggles different palettes
myOSystem->console().togglePalette();
myOSystem.console().togglePalette();
break;
case KBDK_R: // Ctrl-r reloads the currently loaded ROM
myOSystem->reloadConsole();
myOSystem.reloadConsole();
break;
case KBDK_PAGEUP: // Ctrl-PageUp increases Height
myOSystem->console().changeHeight(+1);
myOSystem.console().changeHeight(+1);
break;
case KBDK_PAGEDOWN: // Ctrl-PageDown decreases Height
myOSystem->console().changeHeight(-1);
myOSystem.console().changeHeight(-1);
break;
case KBDK_S: // Ctrl-s saves properties to a file
{
string filename = myOSystem->baseDir() +
myOSystem->console().properties().get(Cartridge_Name) + ".pro";
string filename = myOSystem.baseDir() +
myOSystem.console().properties().get(Cartridge_Name) + ".pro";
ofstream out(filename.c_str(), ios::out);
if(out)
{
myOSystem->console().properties().save(out);
myOSystem.console().properties().save(out);
out.close();
myOSystem->frameBuffer().showMessage("Properties saved");
myOSystem.frameBuffer().showMessage("Properties saved");
}
else
myOSystem->frameBuffer().showMessage("Error saving properties");
myOSystem.frameBuffer().showMessage("Error saving properties");
break;
}
@ -718,7 +718,7 @@ void EventHandler::handleJoyEvent(int stick, int button, uInt8 state)
// enum; subtracting four gives us Controller 0 and 1
if(myState == S_EMULATE)
{
switch(myOSystem->console().controller(Controller::Left).type())
switch(myOSystem.console().controller(Controller::Left).type())
{
case Controller::Keyboard:
if(button < 12) myEvent.set(SA_Key[joy.type-4][button], state);
@ -726,7 +726,7 @@ void EventHandler::handleJoyEvent(int stick, int button, uInt8 state)
default:
if(button < 4) myEvent.set(SA_Button[joy.type-4][button], state);
}
switch(myOSystem->console().controller(Controller::Right).type())
switch(myOSystem.console().controller(Controller::Right).type())
{
case Controller::Keyboard:
if(button < 12) myEvent.set(SA_Key[joy.type-4][button], state);
@ -895,7 +895,7 @@ void EventHandler::handleSystemEvent(SystemEvent e, int data1, int data2)
switch(e)
{
case EVENT_WINDOW_EXPOSED:
myOSystem->frameBuffer().refresh();
myOSystem.frameBuffer().refresh();
break;
default: // handle other events as testing requires
// cerr << "handleSystemEvent: " << e << endl;
@ -964,23 +964,23 @@ void EventHandler::handleEvent(Event::Type event, int state)
return;
case Event::VolumeDecrease:
if(state) myOSystem->sound().adjustVolume(-1);
if(state) myOSystem.sound().adjustVolume(-1);
return;
case Event::VolumeIncrease:
if(state) myOSystem->sound().adjustVolume(+1);
if(state) myOSystem.sound().adjustVolume(+1);
return;
case Event::SaveState:
if(state) myOSystem->state().saveState();
if(state) myOSystem.state().saveState();
return;
case Event::ChangeState:
if(state) myOSystem->state().changeState();
if(state) myOSystem.state().changeState();
return;
case Event::LoadState:
if(state) myOSystem->state().loadState();
if(state) myOSystem.state().loadState();
return;
case Event::TakeSnapshot:
@ -992,11 +992,11 @@ void EventHandler::handleEvent(Event::Type event, int state)
myState == S_DEBUGGER) && state)
{
// Go back to the launcher, or immediately quit
if(myOSystem->settings().getBool("exitlauncher") ||
myOSystem->launcherUsed())
if(myOSystem.settings().getBool("exitlauncher") ||
myOSystem.launcherUsed())
{
myOSystem->deleteConsole();
myOSystem->createLauncher();
myOSystem.deleteConsole();
myOSystem.createLauncher();
}
else
handleEvent(Event::Quit, 1);
@ -1008,7 +1008,7 @@ void EventHandler::handleEvent(Event::Type event, int state)
{
saveKeyMapping();
saveJoyMapping();
myOSystem->quit();
myOSystem.quit();
}
return;
@ -1039,22 +1039,22 @@ void EventHandler::handleEvent(Event::Type event, int state)
// Events which generate messages
case Event::ConsoleColor:
if(state) myOSystem->frameBuffer().showMessage("Color Mode");
if(state) myOSystem.frameBuffer().showMessage("Color Mode");
break;
case Event::ConsoleBlackWhite:
if(state) myOSystem->frameBuffer().showMessage("BW Mode");
if(state) myOSystem.frameBuffer().showMessage("BW Mode");
break;
case Event::ConsoleLeftDiffA:
if(state) myOSystem->frameBuffer().showMessage("Left Difficulty A");
if(state) myOSystem.frameBuffer().showMessage("Left Difficulty A");
break;
case Event::ConsoleLeftDiffB:
if(state) myOSystem->frameBuffer().showMessage("Left Difficulty B");
if(state) myOSystem.frameBuffer().showMessage("Left Difficulty B");
break;
case Event::ConsoleRightDiffA:
if(state) myOSystem->frameBuffer().showMessage("Right Difficulty A");
if(state) myOSystem.frameBuffer().showMessage("Right Difficulty A");
break;
case Event::ConsoleRightDiffB:
if(state) myOSystem->frameBuffer().showMessage("Right Difficulty B");
if(state) myOSystem.frameBuffer().showMessage("Right Difficulty B");
break;
case Event::NoType: // Ignore unmapped events
@ -1261,7 +1261,7 @@ void EventHandler::setKeymap()
{
// Since istringstream swallows whitespace, we have to make the
// delimiters be spaces
string list = myOSystem->settings().getString("keymap");
string list = myOSystem.settings().getString("keymap");
replace(list.begin(), list.end(), ':', ' ');
istringstream buf(list);
@ -1300,7 +1300,7 @@ void EventHandler::setJoymap()
setDefaultJoymap(Event::NoType, kMenuMode);
// Get all mappings from the settings
istringstream buf(myOSystem->settings().getString("joymap"));
istringstream buf(myOSystem.settings().getString("joymap"));
string joymap;
// First check the event type, and disregard the entire mapping if it's invalid
@ -1339,7 +1339,7 @@ void EventHandler::setComboMap()
{
// Since istringstream swallows whitespace, we have to make the
// delimiters be spaces
string list = myOSystem->settings().getString("combomap");
string list = myOSystem.settings().getString("combomap");
replace(list.begin(), list.end(), ':', ' ');
istringstream buf(list);
@ -1623,7 +1623,7 @@ void EventHandler::setDefaultJoymap(Event::Type event, EventMode mode)
else
myJoysticks[i]->eraseEvent(event, mode); // only reset the specific event
}
myOSystem->setDefaultJoymap(event, mode);
myOSystem.setDefaultJoymap(event, mode);
setActionMappings(mode);
#endif
}
@ -1639,7 +1639,7 @@ void EventHandler::saveKeyMapping()
for(int i = 0; i < KBDK_LAST; ++i)
keybuf << ":" << myKeyTable[i][mode];
myOSystem->settings().setValue("keymap", keybuf.str());
myOSystem.settings().setValue("keymap", keybuf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1674,7 +1674,7 @@ void EventHandler::saveJoyMapping()
for(iter = myJoystickMap.begin(); iter != myJoystickMap.end(); ++iter)
joybuf << "^" << iter->second;
myOSystem->settings().setValue("joymap", joybuf.str());
myOSystem.settings().setValue("joymap", joybuf.str());
#endif
}
@ -1692,7 +1692,7 @@ void EventHandler::saveComboMapping()
for(int j = 1; j < kEventsPerCombo; ++j)
buf << "," << myComboTable[i][j];
}
myOSystem->settings().setValue("combomap", buf.str());
myOSystem.settings().setValue("combomap", buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1866,10 +1866,10 @@ void EventHandler::takeSnapshot(uInt32 number)
// Figure out the correct snapshot name
string filename;
bool showmessage = number == 0;
string sspath = myOSystem->snapshotSaveDir() +
(myOSystem->settings().getString("snapname") != "int" ?
myOSystem->romFile().getNameWithExt("")
: myOSystem->console().properties().get(Cartridge_Name));
string sspath = myOSystem.snapshotSaveDir() +
(myOSystem.settings().getString("snapname") != "int" ?
myOSystem.romFile().getNameWithExt("")
: myOSystem.console().properties().get(Cartridge_Name));
// Check whether we want multiple snapshots created
if(number > 0)
@ -1878,7 +1878,7 @@ void EventHandler::takeSnapshot(uInt32 number)
buf << sspath << "_" << hex << setw(8) << setfill('0') << number << ".png";
filename = buf.str();
}
else if(!myOSystem->settings().getBool("sssingle"))
else if(!myOSystem.settings().getBool("sssingle"))
{
// Determine if the file already exists, checking each successive filename
// until one doesn't exist
@ -1902,35 +1902,35 @@ void EventHandler::takeSnapshot(uInt32 number)
filename = sspath + ".png";
// Now create a PNG snapshot
if(myOSystem->settings().getBool("ss1x"))
if(myOSystem.settings().getBool("ss1x"))
{
string msg =
myOSystem->png().saveImage(filename, myOSystem->frameBuffer(),
myOSystem->console().tia(),
myOSystem->console().properties());
myOSystem.png().saveImage(filename, myOSystem.frameBuffer(),
myOSystem.console().tia(),
myOSystem.console().properties());
if(showmessage)
myOSystem->frameBuffer().showMessage(msg);
myOSystem.frameBuffer().showMessage(msg);
}
else
{
// Make sure we have a 'clean' image, with no onscreen messages
myOSystem->frameBuffer().enableMessages(false);
myOSystem.frameBuffer().enableMessages(false);
string msg =
myOSystem->png().saveImage(filename, myOSystem->frameBuffer(),
myOSystem->console().properties());
myOSystem.png().saveImage(filename, myOSystem.frameBuffer(),
myOSystem.console().properties());
// Re-enable old messages
myOSystem->frameBuffer().enableMessages(true);
myOSystem.frameBuffer().enableMessages(true);
if(showmessage)
myOSystem->frameBuffer().showMessage(msg);
myOSystem.frameBuffer().showMessage(msg);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::setMouseControllerMode(const string& enable)
{
if(&myOSystem->console())
if(&myOSystem.console())
{
delete myMouseControl; myMouseControl = NULL;
@ -1941,7 +1941,7 @@ void EventHandler::setMouseControllerMode(const string& enable)
usemouse = false;
else // 'analog'
{
switch(myOSystem->console().controller(Controller::Left).type())
switch(myOSystem.console().controller(Controller::Left).type())
{
case Controller::Paddles:
case Controller::Driving:
@ -1954,7 +1954,7 @@ void EventHandler::setMouseControllerMode(const string& enable)
default:
break;
}
switch(myOSystem->console().controller(Controller::Right).type())
switch(myOSystem.console().controller(Controller::Right).type())
{
case Controller::Paddles:
case Controller::Driving:
@ -1970,9 +1970,9 @@ void EventHandler::setMouseControllerMode(const string& enable)
}
const string& control = usemouse ?
myOSystem->console().properties().get(Controller_MouseAxis) : "none";
myOSystem.console().properties().get(Controller_MouseAxis) : "none";
myMouseControl = new MouseControl(myOSystem->console(), control);
myMouseControl = new MouseControl(myOSystem.console(), control);
myMouseControl->next(); // set first available mode
}
}
@ -1980,7 +1980,7 @@ void EventHandler::setMouseControllerMode(const string& enable)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::setContinuousSnapshots(uInt32 interval)
{
myContSnapshotInterval = (uInt32) myOSystem->frameRate() * interval;
myContSnapshotInterval = (uInt32) myOSystem.frameRate() * interval;
myContSnapshotCounter = 0;
}
@ -1989,44 +1989,44 @@ void EventHandler::enterMenuMode(State state)
{
setEventState(state);
myOverlay->reStack();
myOSystem->sound().mute(true);
myOSystem.sound().mute(true);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::leaveMenuMode()
{
setEventState(S_EMULATE);
myOSystem->sound().mute(false);
myOSystem.sound().mute(false);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventHandler::enterDebugMode()
{
#ifdef DEBUGGER_SUPPORT
if(myState == S_DEBUGGER || !(&myOSystem->console()))
if(myState == S_DEBUGGER || !(&myOSystem.console()))
return false;
// Make sure debugger starts in a consistent state
// This absolutely *has* to come before we actually change to debugger
// mode, since it takes care of locking the debugger state, which will
// probably be modified below
myOSystem->debugger().setStartState();
myOSystem.debugger().setStartState();
setEventState(S_DEBUGGER);
FBInitStatus fbstatus = myOSystem->createFrameBuffer();
FBInitStatus fbstatus = myOSystem.createFrameBuffer();
if(fbstatus != kSuccess)
{
myOSystem->debugger().setQuitState();
myOSystem.debugger().setQuitState();
setEventState(S_EMULATE);
if(fbstatus == kFailTooLarge)
myOSystem->frameBuffer().showMessage("Debugger window too large for screen",
myOSystem.frameBuffer().showMessage("Debugger window too large for screen",
kBottomCenter, true);
return false;
}
myOverlay->reStack();
myOSystem->sound().mute(true);
myOSystem.sound().mute(true);
#else
myOSystem->frameBuffer().showMessage("Debugger support not included",
myOSystem.frameBuffer().showMessage("Debugger support not included",
kBottomCenter, true);
#endif
@ -2042,11 +2042,11 @@ void EventHandler::leaveDebugMode()
return;
// Make sure debugger quits in a consistent state
myOSystem->debugger().setQuitState();
myOSystem.debugger().setQuitState();
setEventState(S_EMULATE);
myOSystem->createFrameBuffer();
myOSystem->sound().mute(false);
myOSystem.createFrameBuffer();
myOSystem.sound().mute(false);
#endif
}
@ -2057,7 +2057,7 @@ void EventHandler::setEventState(State state)
// Normally, the usage of Control key is determined by 'ctrlcombo'
// For certain ROMs it may be forced off, whatever the setting
myUseCtrlKeyFlag = myOSystem->settings().getBool("ctrlcombo");
myUseCtrlKeyFlag = myOSystem.settings().getBool("ctrlcombo");
// Only enable Unicode in GUI modes, since there we need it for ascii data
// Otherwise, it causes a performance hit, so leave it off
@ -2065,37 +2065,37 @@ void EventHandler::setEventState(State state)
{
case S_EMULATE:
myOverlay = NULL;
myOSystem->sound().mute(false);
myOSystem.sound().mute(false);
//FIXME SDL_EnableUNICODE(0);
if(myOSystem->console().controller(Controller::Left).type() ==
if(myOSystem.console().controller(Controller::Left).type() ==
Controller::CompuMate)
myUseCtrlKeyFlag = false;
break;
case S_PAUSE:
myOverlay = NULL;
myOSystem->sound().mute(true);
myOSystem.sound().mute(true);
//FIXME SDL_EnableUNICODE(0);
break;
case S_MENU:
myOverlay = &myOSystem->menu();
myOverlay = &myOSystem.menu();
//FIXME SDL_EnableUNICODE(1);
break;
case S_CMDMENU:
myOverlay = &myOSystem->commandMenu();
myOverlay = &myOSystem.commandMenu();
//FIXME SDL_EnableUNICODE(1);
break;
case S_LAUNCHER:
myOverlay = &myOSystem->launcher();
myOverlay = &myOSystem.launcher();
//FIXME SDL_EnableUNICODE(1);
break;
#ifdef DEBUGGER_SUPPORT
case S_DEBUGGER:
myOverlay = &myOSystem->debugger();
myOverlay = &myOSystem.debugger();
//FIXME SDL_EnableUNICODE(1);
break;
#endif
@ -2106,15 +2106,15 @@ void EventHandler::setEventState(State state)
}
// Inform various subsystems about the new state
myOSystem->stateChanged(myState);
if(&myOSystem->frameBuffer())
myOSystem.stateChanged(myState);
if(&myOSystem.frameBuffer())
{
myOSystem->frameBuffer().stateChanged(myState);
myOSystem->frameBuffer().setCursorState();
myOSystem.frameBuffer().stateChanged(myState);
myOSystem.frameBuffer().setCursorState();
}
if(&myOSystem->console())
if(&myOSystem.console())
{
myOSystem->console().stateChanged(myState);
myOSystem.console().stateChanged(myState);
}
// Always clear any pending events when changing states

View File

@ -86,7 +86,7 @@ class EventHandler
/**
Create a new event handler object
*/
EventHandler(OSystem* osystem);
EventHandler(OSystem& osystem);
/**
Destructor
@ -319,7 +319,7 @@ class EventHandler
protected:
// Global OSystem object
OSystem* myOSystem;
OSystem& myOSystem;
/**
Methods which are called by derived classes to handle specific types

View File

@ -21,9 +21,8 @@
#include "FBSurface.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FBSurface::FBSurface(const uInt32* palette)
: myPalette(palette),
myPixels(NULL),
FBSurface::FBSurface()
: myPixels(NULL),
myPitch(0)
{
// NOTE: myPixels and myPitch MUST be set in child classes that inherit
@ -278,3 +277,6 @@ void FBSurface::drawSurface(const FBSurface* surface)
dst += myPitch;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt32* FBSurface::myPalette = 0;

View File

@ -21,6 +21,7 @@
#define FBSURFACE_HXX
class FrameBuffer;
class TIASurface;
#include "bspf.hxx"
#include "Font.hxx"
@ -51,11 +52,13 @@ enum FrameStyle {
class FBSurface
{
friend class TIASurface;
public:
/**
Creates a new FBSurface object
*/
FBSurface(const uInt32* palette);
FBSurface();
/**
Destructor
@ -259,17 +262,6 @@ class FBSurface
*/
virtual void setStaticContents(const uInt32* pixels, uInt32 pitch) = 0;
/**
This method should be called to modify the interpolation and
blending effects to be applied to this surface.
@param smoothScale Whether to use interpolation during scaling
@param useBlend Whether the surface should use alpha blending
@param blendAlpha The alpha to use during blending (if used)
*/
virtual void setInterpolationAndBlending(bool smoothScale,
bool useBlend, uInt32 blendAlpha) = 0;
/**
This method should be called to translate the given coordinates
to the (destination) surface coordinates.
@ -302,10 +294,35 @@ class FBSurface
*/
virtual void reload() = 0;
static void setPalette(const uInt32* palette) { myPalette = palette; }
protected:
const uInt32* myPalette;
/**
The rendering attributes that can be modified for this texture.
These probably can only be implemented in child FBSurfaces where
the specific functionality actually exists.
*/
struct Attributes {
bool smoothing; // Scaling is smoothed or blocky
bool blending; // Blending is enabled
uInt32 blendalpha; // Alpha to use in blending mode (0-100%)
};
/**
The child class chooses which (if any) of the actual attributes
can be applied.
@param immediate Whether to re-initialize the surface immediately
with the new attributes, or wait until manually
reloaded
*/
virtual void applyAttributes(bool immediate = true) = 0;
protected:
static const uInt32* myPalette;
uInt32* myPixels;
uInt32 myPitch;
Attributes myAttributes;
};
#endif

View File

@ -38,6 +38,7 @@
#include "TIA.hxx"
#include "FBSurface.hxx"
#include "TIASurface.hxx"
#include "FrameBuffer.hxx"
#ifdef DEBUGGER_SUPPORT
@ -45,19 +46,15 @@
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBuffer::FrameBuffer(OSystem* osystem)
FrameBuffer::FrameBuffer(OSystem& osystem)
: myOSystem(osystem),
myRedrawEntireFrame(true),
myUsePhosphor(false),
myPhosphorBlend(77),
myInitializedCount(0),
myPausedCount(0)
myPausedCount(0),
myTIASurface(NULL)
{
myMsg.surface = myStatsMsg.surface = NULL;
myMsg.enabled = myStatsMsg.enabled = false;
// Load NTSC filter settings
myNTSCFilter.loadConfig(myOSystem->settings());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -67,6 +64,7 @@ FrameBuffer::~FrameBuffer(void)
delete myInfoFont;
delete mySmallFont;
delete myLauncherFont;
delete myTIASurface;
// Free all allocated surfaces
while(!mySurfaceList.empty())
@ -85,7 +83,7 @@ bool FrameBuffer::initialize()
// 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");
const GUI::Size& s = myOSystem.settings().getSize("maxres");
if(s.w > 0 && s.h > 0)
{
query_w = s.w;
@ -126,7 +124,7 @@ bool FrameBuffer::initialize()
// very small screens
if(!smallScreen)
{
const string& lf = myOSystem->settings().getString("launcherfont");
const string& lf = myOSystem.settings().getString("launcherfont");
if(lf == "small")
myLauncherFont = new GUI::Font(GUI::consoleDesc);
else if(lf == "medium")
@ -150,6 +148,20 @@ bool FrameBuffer::initialize()
myTIAZoomLevels.push_back(desc.str(), zoom);
}
// Set palette for GUI (upper area of array, doesn't change during execution)
for(int i = 0, j = 256; i < kNumColors-256; ++i, ++j)
{
Uint8 r = (ourGUIColors[i] >> 16) & 0xff;
Uint8 g = (ourGUIColors[i] >> 8) & 0xff;
Uint8 b = ourGUIColors[i] & 0xff;
myPalette[j] = mapRGB(r, g, b);
}
FBSurface::setPalette(myPalette);
// Create a TIA surface; we need it for rendering TIA images
myTIASurface = new TIASurface(*this, myOSystem);
return true;
}
@ -181,7 +193,7 @@ FBInitStatus FrameBuffer::createDisplay(const string& title,
return kFailTooLarge;
// FIXSDL - remove size limitations here?
if(myOSystem->settings().getString("fullscreen") == "1")
if(myOSystem.settings().getString("fullscreen") == "1")
{
if(myDesktopSize.w < width || myDesktopSize.h < height)
return kFailTooLarge;
@ -208,15 +220,21 @@ FBInitStatus FrameBuffer::createDisplay(const string& title,
myScreenSize = mode.screen;
if(width <= (uInt32)myScreenSize.w && height <= (uInt32)myScreenSize.h)
{
if(setVideoMode(myScreenTitle, mode, useFullscreen))
if(setVideoMode(myScreenTitle, mode))
{
// Inform TIA surface about new mode
if(myOSystem.eventHandler().state() != EventHandler::S_LAUNCHER &&
myOSystem.eventHandler().state() != EventHandler::S_DEBUGGER)
myTIASurface->initialize(myOSystem.console(), mode);
// Did we get the requested fullscreen state?
myOSystem->settings().setValue("fullscreen", fullScreen());
myOSystem.settings().setValue("fullscreen", fullScreen());
resetSurfaces();
setCursorState();
}
else
{
myOSystem->logMessage("ERROR: Couldn't initialize video subsystem", 0);
myOSystem.logMessage("ERROR: Couldn't initialize video subsystem", 0);
return kFailNotSupported;
}
}
@ -245,15 +263,14 @@ FBInitStatus FrameBuffer::createDisplay(const string& title,
// Take care of some items that are only done once per framebuffer creation.
if(myInitializedCount == 1)
{
myOSystem->logMessage(about(), 1);
setUIPalette();
myOSystem.logMessage(about(), 1);
setWindowIcon();
}
else
{
string post_about = about();
if(post_about != pre_about)
myOSystem->logMessage(post_about, 1);
myOSystem.logMessage(post_about, 1);
}
return kSuccess;
@ -265,31 +282,31 @@ void FrameBuffer::update()
// Determine which mode we are in (from the EventHandler)
// Take care of S_EMULATE mode here, otherwise let the GUI
// figure out what to draw
switch(myOSystem->eventHandler().state())
switch(myOSystem.eventHandler().state())
{
case EventHandler::S_EMULATE:
{
// Run the console for one frame
// Note that the debugger can cause a breakpoint to occur, which changes
// the EventHandler state 'behind our back' - we need to check for that
myOSystem->console().tia().update();
myOSystem.console().tia().update();
#ifdef DEBUGGER_SUPPORT
if(myOSystem->eventHandler().state() != EventHandler::S_EMULATE) break;
if(myOSystem.eventHandler().state() != EventHandler::S_EMULATE) break;
#endif
if(myOSystem->eventHandler().frying())
myOSystem->console().fry();
if(myOSystem.eventHandler().frying())
myOSystem.console().fry();
// And update the screen
drawTIA(myRedrawEntireFrame);
drawTIA();
// Show frame statistics
if(myStatsMsg.enabled)
{
const ConsoleInfo& info = myOSystem->console().about();
const ConsoleInfo& info = myOSystem.console().about();
char msg[30];
BSPF_snprintf(msg, 30, "%3u @ %3.2ffps => %s",
myOSystem->console().tia().scanlines(),
myOSystem->console().getFramerate(), info.DisplayFormat.c_str());
myOSystem.console().tia().scanlines(),
myOSystem.console().getFramerate(), info.DisplayFormat.c_str());
myStatsMsg.surface->fillRect(0, 0, myStatsMsg.w, myStatsMsg.h, kBGColor);
myStatsMsg.surface->drawString(infoFont(),
msg, 1, 1, myStatsMsg.w, myStatsMsg.color, kTextAlignLeft);
@ -306,10 +323,10 @@ void FrameBuffer::update()
{
// Only update the screen if it's been invalidated
if(myRedrawEntireFrame)
drawTIA(true);
drawTIA();
// Show a pause message every 5 seconds
if(myPausedCount++ >= 7*myOSystem->frameRate())
if(myPausedCount++ >= 7*myOSystem.frameRate())
{
myPausedCount = 0;
showMessage("Paused", kMiddleCenter);
@ -321,7 +338,7 @@ void FrameBuffer::update()
{
// When onscreen messages are enabled in double-buffer mode,
// a full redraw is required
myOSystem->menu().draw(myMsg.enabled && isDoubleBuffered());
myOSystem.menu().draw(myMsg.enabled && isDoubleBuffered());
break; // S_MENU
}
@ -329,7 +346,7 @@ void FrameBuffer::update()
{
// When onscreen messages are enabled in double-buffer mode,
// a full redraw is required
myOSystem->commandMenu().draw(myMsg.enabled && isDoubleBuffered());
myOSystem.commandMenu().draw(myMsg.enabled && isDoubleBuffered());
break; // S_CMDMENU
}
@ -337,7 +354,7 @@ void FrameBuffer::update()
{
// When onscreen messages are enabled in double-buffer mode,
// a full redraw is required
myOSystem->launcher().draw(myMsg.enabled && isDoubleBuffered());
myOSystem.launcher().draw(myMsg.enabled && isDoubleBuffered());
break; // S_LAUNCHER
}
@ -346,7 +363,7 @@ void FrameBuffer::update()
{
// When onscreen messages are enabled in double-buffer mode,
// a full redraw is required
myOSystem->debugger().draw(myMsg.enabled && isDoubleBuffered());
myOSystem.debugger().draw(myMsg.enabled && isDoubleBuffered());
break; // S_DEBUGGER
}
#endif
@ -371,7 +388,7 @@ void FrameBuffer::showMessage(const string& message, MessagePosition position,
bool force)
{
// Only show messages if they've been enabled
if(!(force || myOSystem->settings().getBool("uimessages")))
if(!(force || myOSystem.settings().getBool("uimessages")))
return;
// Erase old messages on the screen
@ -383,7 +400,7 @@ void FrameBuffer::showMessage(const string& message, MessagePosition position,
// Precompute the message coordinates
myMsg.text = message;
myMsg.counter = uInt32(myOSystem->frameRate()) << 1; // Show message for 2 seconds
myMsg.counter = uInt32(myOSystem.frameRate()) << 1; // Show message for 2 seconds
myMsg.color = kBtnTextColor;
myMsg.w = font().getStringWidth(myMsg.text) + 10;
@ -397,13 +414,13 @@ void FrameBuffer::showMessage(const string& message, MessagePosition position,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::toggleFrameStats()
{
showFrameStats(!myOSystem->settings().getBool("stats"));
showFrameStats(!myOSystem.settings().getBool("stats"));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::showFrameStats(bool enable)
{
myOSystem->settings().setValue("stats", enable);
myOSystem.settings().setValue("stats", enable);
myStatsMsg.enabled = enable;
refresh();
}
@ -414,7 +431,7 @@ void FrameBuffer::enableMessages(bool enable)
if(enable)
{
// Only re-enable frame stats if they were already enabled before
myStatsMsg.enabled = myOSystem->settings().getBool("stats");
myStatsMsg.enabled = myOSystem.settings().getBool("stats");
}
else
{
@ -502,6 +519,15 @@ inline void FrameBuffer::drawMessage()
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inline void FrameBuffer::drawTIA()
{
myTIASurface->render();
// Let postFrameUpdate() know that a change has been made
//FIXSDL invalidate();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::refresh()
{
@ -514,66 +540,66 @@ void FrameBuffer::refresh()
// This method is in essence a FULL refresh, putting all rendering
// buffers in a known, fully redrawn state
switch(myOSystem->eventHandler().state())
switch(myOSystem.eventHandler().state())
{
case EventHandler::S_EMULATE:
case EventHandler::S_PAUSE:
invalidate();
drawTIA(true);
drawTIA();
if(isDoubleBuffered())
{
postFrameUpdate();
invalidate();
drawTIA(true);
drawTIA();
}
break;
case EventHandler::S_MENU:
invalidate();
drawTIA(true);
myOSystem->menu().draw(true);
drawTIA();
myOSystem.menu().draw(true);
if(isDoubleBuffered())
{
postFrameUpdate();
invalidate();
drawTIA(true);
myOSystem->menu().draw(true);
drawTIA();
myOSystem.menu().draw(true);
}
break;
case EventHandler::S_CMDMENU:
invalidate();
drawTIA(true);
myOSystem->commandMenu().draw(true);
drawTIA();
myOSystem.commandMenu().draw(true);
if(isDoubleBuffered())
{
postFrameUpdate();
invalidate();
drawTIA(true);
myOSystem->commandMenu().draw(true);
drawTIA();
myOSystem.commandMenu().draw(true);
}
break;
case EventHandler::S_LAUNCHER:
invalidate();
myOSystem->launcher().draw(true);
myOSystem.launcher().draw(true);
if(isDoubleBuffered())
{
postFrameUpdate();
invalidate();
myOSystem->launcher().draw(true);
myOSystem.launcher().draw(true);
}
break;
#ifdef DEBUGGER_SUPPORT
case EventHandler::S_DEBUGGER:
invalidate();
myOSystem->debugger().draw(true);
myOSystem.debugger().draw(true);
if(isDoubleBuffered())
{
postFrameUpdate();
invalidate();
myOSystem->debugger().draw(true);
myOSystem.debugger().draw(true);
}
break;
#endif
@ -583,59 +609,6 @@ void FrameBuffer::refresh()
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setNTSC(NTSCFilter::Preset preset, bool show)
{
ostringstream buf;
if(preset == NTSCFilter::PRESET_OFF)
{
enableNTSC(false);
buf << "TV filtering disabled";
}
else
{
enableNTSC(true);
const string& mode = myNTSCFilter.setPreset(preset);
buf << "TV filtering (" << mode << " mode)";
}
myOSystem->settings().setValue("tv.filter", (int)preset);
if(show) showMessage(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setScanlineIntensity(int amount)
{
ostringstream buf;
if(ntscEnabled())
{
uInt32 intensity = enableScanlines(amount);
buf << "Scanline intensity at " << intensity << "%";
myOSystem->settings().setValue("tv.scanlines", intensity);
}
else
buf << "Scanlines only available in TV filtering mode";
showMessage(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::toggleScanlineInterpolation()
{
ostringstream buf;
if(ntscEnabled())
{
bool enable = !myOSystem->settings().getBool("tv.scaninter");
enableScanlineInterpolation(enable);
buf << "Scanline interpolation " << (enable ? "enabled" : "disabled");
myOSystem->settings().setValue("tv.scaninter", enable);
}
else
buf << "Scanlines only available in TV filtering mode";
showMessage(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameBuffer::allocateSurface(int w, int h)
{
@ -646,7 +619,7 @@ uInt32 FrameBuffer::allocateSurface(int w, int h)
mySurfaceList.insert(make_pair((uInt32)mySurfaceList.size(), surface));
// Return a reference to it
return mySurfaceList.size() - 1;
return (uInt32)mySurfaceList.size() - 1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -657,7 +630,7 @@ FBSurface* FrameBuffer::surface(uInt32 id) const
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::resetSurfaces(FBSurface* tiasurface)
void FrameBuffer::resetSurfaces()
{
// Free all resources for each surface, then reload them
// Due to possible timing and/or synchronization issues, all free()'s
@ -668,75 +641,30 @@ void FrameBuffer::resetSurfaces(FBSurface* tiasurface)
map<uInt32,FBSurface*>::iterator iter;
for(iter = mySurfaceList.begin(); iter != mySurfaceList.end(); ++iter)
iter->second->free();
if(tiasurface)
tiasurface->free();
for(iter = mySurfaceList.begin(); iter != mySurfaceList.end(); ++iter)
iter->second->reload();
if(tiasurface)
tiasurface->reload();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameBuffer::tiaPixel(uInt32 idx, uInt8 shift) const
void FrameBuffer::setPalette(const uInt32* palette)
{
uInt8 c = *(myOSystem->console().tia().currentFrameBuffer() + idx) | shift;
uInt8 p = *(myOSystem->console().tia().previousFrameBuffer() + idx) | shift;
return (!myUsePhosphor ? myDefPalette[c] : myAvgPalette[c][p]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setTIAPalette(const uInt32* palette)
{
int i, j;
cerr << "FrameBuffer::setPalette\n";
// Set palette for normal fill
for(i = 0; i < 256; ++i)
for(int i = 0; i < 256; ++i)
{
Uint8 r = (palette[i] >> 16) & 0xff;
Uint8 g = (palette[i] >> 8) & 0xff;
Uint8 b = palette[i] & 0xff;
myDefPalette[i] = mapRGB(r, g, b);
myPalette[i] = mapRGB(r, g, b);
}
// Set palette for phosphor effect
for(i = 0; i < 256; ++i)
{
for(j = 0; j < 256; ++j)
{
uInt8 ri = (palette[i] >> 16) & 0xff;
uInt8 gi = (palette[i] >> 8) & 0xff;
uInt8 bi = palette[i] & 0xff;
uInt8 rj = (palette[j] >> 16) & 0xff;
uInt8 gj = (palette[j] >> 8) & 0xff;
uInt8 bj = palette[j] & 0xff;
Uint8 r = (Uint8) getPhosphor(ri, rj);
Uint8 g = (Uint8) getPhosphor(gi, gj);
Uint8 b = (Uint8) getPhosphor(bi, bj);
myAvgPalette[i][j] = mapRGB(r, g, b);
}
}
// Let the TIA surface know about the new palette
myTIASurface->setPalette(myPalette, palette);
myRedrawEntireFrame = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setUIPalette()
{
// Set palette for GUI
for(int i = 0, j = 256; i < kNumColors-256; ++i, ++j)
{
Uint8 r = (ourGUIColors[i] >> 16) & 0xff;
Uint8 g = (ourGUIColors[i] >> 8) & 0xff;
Uint8 b = ourGUIColors[i] & 0xff;
myDefPalette[j] = mapRGB(r, g, b);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::stateChanged(EventHandler::State state)
{
@ -758,7 +686,7 @@ enableFullscreen(enable);
#if 0 //FIXSDL
#ifdef WINDOWED_SUPPORT
// '-1' means fullscreen mode is completely disabled
bool full = enable && myOSystem->settings().getString("fullscreen") != "-1";
bool full = enable && myOSystem.settings().getString("fullscreen") != "-1";
setHint(kFullScreen, full);
// Do a dummy call to getSavedVidMode to set up the modelists
@ -782,7 +710,7 @@ void FrameBuffer::toggleFullscreen()
bool FrameBuffer::changeWindowedVidMode(int direction)
{
#ifdef WINDOWED_SUPPORT
EventHandler::State state = myOSystem->eventHandler().state();
EventHandler::State state = myOSystem.eventHandler().state();
bool tiaMode = (state != EventHandler::S_DEBUGGER &&
state != EventHandler::S_LAUNCHER);
@ -800,10 +728,11 @@ bool FrameBuffer::changeWindowedVidMode(int direction)
const VideoMode& mode = myCurrentModeList->current();
myImageRect = mode.image;
myScreenSize = mode.screen;
if(setVideoMode(myScreenTitle, mode, false))
if(setVideoMode(myScreenTitle, mode))
{
resetSurfaces();
showMessage(mode.description);
myOSystem->settings().setValue("tia.zoom", mode.zoom);
myOSystem.settings().setValue("tia.zoom", mode.zoom);
refresh();
return true;
}
@ -817,29 +746,20 @@ void FrameBuffer::setCursorState()
// Always grab mouse in fullscreen or during emulation (if enabled),
// and don't show the cursor during emulation
bool emulation =
myOSystem->eventHandler().state() == EventHandler::S_EMULATE;
myOSystem.eventHandler().state() == EventHandler::S_EMULATE;
grabMouse(fullScreen() ||
(emulation && myOSystem->settings().getBool("grabmouse")));
(emulation && myOSystem.settings().getBool("grabmouse")));
showCursor(!emulation);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::toggleGrabMouse()
{
bool state = myOSystem->settings().getBool("grabmouse");
myOSystem->settings().setValue("grabmouse", !state);
bool state = myOSystem.settings().getBool("grabmouse");
myOSystem.settings().setValue("grabmouse", !state);
setCursorState();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 FrameBuffer::getPhosphor(uInt8 c1, uInt8 c2) const
{
if(c2 > c1)
BSPF_swap(c1, c2);
return ((c1 - c2) * myPhosphorBlend)/100 + c2;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameBuffer::maxWindowSizeForScreen(uInt32 baseWidth, uInt32 baseHeight,
uInt32 screenWidth, uInt32 screenHeight)
@ -867,7 +787,7 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
// Check if zooming is allowed for this state (currently only allowed
// for TIA screens)
EventHandler::State state = myOSystem->eventHandler().state();
EventHandler::State state = myOSystem.eventHandler().state();
bool tiaMode = (state != EventHandler::S_DEBUGGER &&
state != EventHandler::S_LAUNCHER);
@ -880,8 +800,8 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
myDesktopSize.w, myDesktopSize.h);
// Aspect ratio
bool ntsc = myOSystem->console().about().InitialFrameRate == "60";
uInt32 aspect = myOSystem->settings().getInt(ntsc ?
bool ntsc = myOSystem.console().about().InitialFrameRate == "60";
uInt32 aspect = myOSystem.settings().getInt(ntsc ?
"tia.aspectn" : "tia.aspectp");
// Figure our the smallest zoom level we can use
@ -925,9 +845,9 @@ cerr << "Windowed modes:\n" << myWindowedModeList << endl
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const FrameBuffer::VideoMode& FrameBuffer::getSavedVidMode(bool fullscreen)
const VideoMode& FrameBuffer::getSavedVidMode(bool fullscreen)
{
EventHandler::State state = myOSystem->eventHandler().state();
EventHandler::State state = myOSystem.eventHandler().state();
if(fullscreen)
myCurrentModeList = &myFullscreenModeList;
@ -940,7 +860,7 @@ const FrameBuffer::VideoMode& FrameBuffer::getSavedVidMode(bool fullscreen)
if(state == EventHandler::S_DEBUGGER || state == EventHandler::S_LAUNCHER)
myCurrentModeList->setZoom(1);
else
myCurrentModeList->setZoom(myOSystem->settings().getInt("tia.zoom"));
myCurrentModeList->setZoom(myOSystem.settings().getInt("tia.zoom"));
return myCurrentModeList->current();
}
@ -950,7 +870,7 @@ const FrameBuffer::VideoMode& FrameBuffer::getSavedVidMode(bool fullscreen)
// VideoMode implementation
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBuffer::VideoMode::VideoMode()
VideoMode::VideoMode()
: fullscreen(false),
zoom(1),
description("")
@ -958,7 +878,7 @@ FrameBuffer::VideoMode::VideoMode()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBuffer::VideoMode::VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
VideoMode::VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
bool full, uInt32 z, const string& desc)
: fullscreen(full),
zoom(z),
@ -975,7 +895,7 @@ FrameBuffer::VideoMode::VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::VideoMode::applyAspectCorrection(uInt32 aspect, uInt32 stretch)
void VideoMode::applyAspectCorrection(uInt32 aspect, uInt32 stretch)
{
// Width is modified by aspect ratio; other factors may be applied below
uInt32 iw = (uInt32)(float(image.width() * aspect) / 100.0);
@ -993,7 +913,7 @@ void FrameBuffer::VideoMode::applyAspectCorrection(uInt32 aspect, uInt32 stretch
float scaleY = float(mode.image_h) / mode.screen_h;
// Scale to actual or integral factors
if(myOSystem->settings().getBool("gl_fsscale"))
if(myOSystem.settings().getBool("gl_fsscale"))
{
// Scale to full (non-integral) available space
if(scaleX > scaleY)
@ -1084,7 +1004,7 @@ void FrameBuffer::VideoModeList::previous()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const FrameBuffer::VideoMode& FrameBuffer::VideoModeList::current() const
const VideoMode& FrameBuffer::VideoModeList::current() const
{
return myModeList[myIdx];
}

View File

@ -30,12 +30,12 @@ namespace GUI {
class Font;
}
#include "FBSurface.hxx"
#include "EventHandler.hxx"
#include "Rect.hxx"
#include "StringList.hxx"
#include "NTSCFilter.hxx"
#include "Variant.hxx"
#include "FBSurface.hxx"
#include "TIASurface.hxx"
#include "bspf.hxx"
// Return values for initialization of framebuffer window
@ -85,6 +85,39 @@ enum {
kNumColors
};
// Contains all relevant info for the dimensions of a video screen
// Also takes care of the case when the image should be 'centered'
// within the given screen:
// 'image' is the image dimensions into the screen
// 'screen' are the dimensions of the screen itself
class VideoMode
{
friend class FrameBuffer;
public:
GUI::Rect image;
GUI::Size screen;
bool fullscreen;
uInt32 zoom;
string description;
public:
VideoMode();
VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, bool full,
uInt32 z = 1, const string& desc = "");
friend ostream& operator<<(ostream& os, const VideoMode& vm)
{
os << "image=" << vm.image << " screen=" << vm.screen << endl
<< "full= " << vm.fullscreen << " zoom=" << vm.zoom
<< " desc=" << vm.description;
return os;
}
private:
void applyAspectCorrection(uInt32 aspect, uInt32 stretch = false);
};
/**
This class encapsulates all video buffers and is the basis for the video
display in Stella. All graphics ports should derive from this class for
@ -107,7 +140,7 @@ class FrameBuffer
/**
Creates a new Frame Buffer
*/
FrameBuffer(OSystem* osystem);
FrameBuffer(OSystem& osystem);
/**
Destructor
@ -210,6 +243,11 @@ class FrameBuffer
*/
const VariantList& supportedRenderers() const { return myRenderers; }
/**
Get the supported TIA zoom levels (windowed mode) for the framebuffer.
*/
const VariantList& supportedTIAZoomLevels() const { return myTIAZoomLevels; }
/**
Get the font object(s) of the framebuffer
*/
@ -218,6 +256,11 @@ class FrameBuffer
const GUI::Font& smallFont() const { return *mySmallFont; }
const GUI::Font& launcherFont() const { return *myLauncherFont; }
/**
Get the TIA surface associated with the framebuffer.
*/
TIASurface& tiaSurface() const { return *myTIASurface; }
/**
Refresh display according to the current state, taking single vs.
double-buffered modes into account, and redrawing accordingly.
@ -256,91 +299,18 @@ class FrameBuffer
*/
void toggleGrabMouse();
/**
Get the supported TIA zoom levels (windowed mode) for the framebuffer.
*/
const VariantList& supportedTIAZoomLevels() { return myTIAZoomLevels; }
/**
Get the TIA pixel associated with the given TIA buffer index,
shifting by the given offset (for greyscale values).
*/
uInt32 tiaPixel(uInt32 idx, uInt8 shift = 0) const;
/**
Set up the TIA/emulation palette for a screen of any depth > 8.
@param palette The array of colors
*/
virtual void setTIAPalette(const uInt32* palette);
void setPalette(const uInt32* palette);
/**
Informs the Framebuffer of a change in EventHandler state.
*/
void stateChanged(EventHandler::State state);
/**
Get the NTSCFilter object associated with the framebuffer
*/
NTSCFilter& ntsc() { return myNTSCFilter; }
/**
Use NTSC filtering effects specified by the given preset.
*/
void setNTSC(NTSCFilter::Preset preset, bool show = true);
/**
Increase/decrease current scanline intensity by given relative amount.
*/
void setScanlineIntensity(int relative);
/**
Toggles interpolation/smoothing of scanlines in TV modes.
*/
void toggleScanlineInterpolation();
/**
Used to calculate an averaged color for the 'phosphor' effect.
@param c1 Color 1
@param c2 Color 2
@return Averaged value of the two colors
*/
uInt8 getPhosphor(uInt8 c1, uInt8 c2) const;
// Contains all relevant info for the dimensions of a video screen
// Also takes care of the case when the image should be 'centered'
// within the given screen:
// 'image' is the image dimensions into the screen
// 'screen' are the dimensions of the screen itself
class VideoMode
{
friend class FrameBuffer;
public:
GUI::Rect image;
GUI::Size screen;
bool fullscreen;
uInt32 zoom;
string description;
public:
VideoMode();
VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, bool full,
uInt32 z = 1, const string& desc = "");
friend ostream& operator<<(ostream& os, const VideoMode& vm)
{
os << "image=" << vm.image << " screen=" << vm.screen << endl
<< "desc=" << vm.description << " zoom=" << vm.zoom;
return os;
}
private:
void applyAspectCorrection(uInt32 aspect, uInt32 stretch = false);
};
//////////////////////////////////////////////////////////////////////
// The following methods are system-specific and can/must be
// implemented in derived classes.
@ -356,18 +326,6 @@ class FrameBuffer
*/
virtual bool fullScreen() const = 0;
/**
Enable/disable/query NTSC filtering effects.
*/
virtual void enableNTSC(bool enable) { }
virtual bool ntscEnabled() const { return false; }
virtual string effectsInfo() const { return "None / not available"; }
/**
Enable/disable phosphor effect.
*/
virtual void enablePhosphor(bool enable, int blend) = 0;
/**
This method is called to retrieve the R/G/B data from the given pixel.
@ -411,16 +369,14 @@ class FrameBuffer
virtual void queryHardware(uInt32& w, uInt32& h, VariantList& ren) = 0;
/**
This method is called to change to the given video mode. If the mode
is successfully changed, 'mode' holds the actual dimensions used.
This method is called to change to the given video mode.
@param title The title for the created window
@param mode The video mode to use
@param full Whether this is a fullscreen or windowed mode
@return False on any errors, else true
*/
virtual bool setVideoMode(const string& title, const VideoMode& mode, bool full) = 0;
virtual bool setVideoMode(const string& title, const VideoMode& mode) = 0;
/**
Enables/disables fullscreen mode.
@ -444,16 +400,6 @@ class FrameBuffer
*/
virtual FBSurface* createSurface(uInt32 w, uInt32 h) const = 0;
/**
Change scanline intensity and interpolation.
@param relative If non-zero, change current intensity by
'relative' amount, otherwise set to 'absolute'
@return New current intensity
*/
virtual uInt32 enableScanlines(int relative, int absolute = 50) { return absolute; }
virtual void enableScanlineInterpolation(bool enable) { }
/**
Grabs or ungrabs the mouse based on the given boolean value.
*/
@ -464,12 +410,6 @@ class FrameBuffer
*/
virtual void setWindowIcon() = 0;
/**
This method should be called anytime the TIA needs to be redrawn
to the screen (full indicating that a full redraw is required).
*/
virtual void drawTIA(bool full) = 0;
/**
This method is called after any drawing is done (per-frame).
*/
@ -480,35 +420,15 @@ class FrameBuffer
*/
virtual string about() const = 0;
/**
Issues a 'free' and 'reload' instruction to all surfaces that the
framebuffer knows about.
*/
void resetSurfaces(FBSurface* tiasurface = (FBSurface*)0);
protected:
// The parent system for the framebuffer
OSystem* myOSystem;
OSystem& myOSystem;
// Indicates if the entire frame need to redrawn
bool myRedrawEntireFrame;
// NTSC object to use in TIA rendering mode
NTSCFilter myNTSCFilter;
// Use phosphor effect (aka no flicker on 30Hz screens)
bool myUsePhosphor;
// Amount to blend when using phosphor effect
int myPhosphorBlend;
// TIA palettes for normal and phosphor modes
// 'myDefPalette' also contains the UI palette
Uint32 myDefPalette[256+kNumColors];
Uint32 myAvgPalette[256][256];
// Names of the TIA zoom levels that can be used for this framebuffer
VariantList myTIAZoomLevels;
// Color palette for TIA and UI modes
Uint32 myPalette[256+kNumColors];
private:
/**
@ -516,6 +436,18 @@ class FrameBuffer
*/
void drawMessage();
/**
This method should be called anytime the TIA needs to be redrawn
to the screen.
*/
void drawTIA();
/**
Issues a 'free' and 'reload' instruction to all surfaces that the
framebuffer knows about.
*/
void resetSurfaces();
/**
Calculate the maximum level by which the base window can be zoomed and
still fit in the given screen dimensions.
@ -544,11 +476,6 @@ class FrameBuffer
*/
const VideoMode& getSavedVidMode(bool fullscreen);
/**
Set up the user interface palette for a screen of any depth > 8.
*/
void setUIPalette();
private:
/**
This class implements an iterator around an array of VideoMode objects.
@ -566,7 +493,7 @@ class FrameBuffer
uInt32 size() const;
void previous();
const FrameBuffer::VideoMode& current() const;
const VideoMode& current() const;
void next();
void setZoom(uInt32 zoom);
@ -619,6 +546,9 @@ class FrameBuffer
// The font object to use for the ROM launcher
GUI::Font* myLauncherFont;
// The TIASurface class takes responsibility for TIA rendering
TIASurface* myTIASurface;
// Used for onscreen messages and frame statistics
// (scanline count and framerate)
struct Message {
@ -638,6 +568,9 @@ class FrameBuffer
VideoModeList myFullscreenModeList;
VideoModeList* myCurrentModeList;
// Names of the TIA zoom levels that can be used for this framebuffer
VariantList myTIAZoomLevels;
// Holds a reference to all the surfaces that have been created
map<uInt32,FBSurface*> mySurfaceList;

View File

@ -74,7 +74,7 @@ class MediaFactory
#endif
}
static Settings* createSettings(OSystem* osystem)
static Settings* createSettings(OSystem& osystem)
{
#if defined(BSPF_UNIX)
return new SettingsUNIX(osystem);
@ -87,12 +87,12 @@ class MediaFactory
#endif
}
static FrameBuffer* createVideo(OSystem* osystem)
static FrameBuffer* createVideo(OSystem& osystem)
{
return new FrameBufferSDL2(osystem);
}
static Sound* createAudio(OSystem* osystem)
static Sound* createAudio(OSystem& osystem)
{
#ifdef SOUND_SUPPORT
return new SoundSDL2(osystem);
@ -101,7 +101,7 @@ class MediaFactory
#endif
}
static EventHandler* createEventHandler(OSystem* osystem)
static EventHandler* createEventHandler(OSystem& osystem)
{
return new EventHandlerSDL2(osystem);
}

View File

@ -115,7 +115,7 @@ OSystem::OSystem()
<< " [" << BSPF_ARCH << "]";
myBuildInfo = info.str();
mySettings = MediaFactory::createSettings(this);
mySettings = MediaFactory::createSettings(*this);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -174,12 +174,12 @@ bool OSystem::create()
// Get relevant information about the video hardware
// This must be done before any graphics context is created, since
// it may be needed to initialize the size of graphical objects
myFrameBuffer = MediaFactory::createVideo(this);
myFrameBuffer = MediaFactory::createVideo(*this);
if(!myFrameBuffer->initialize())
return false;
// Create the event handler for the system
myEventHandler = MediaFactory::createEventHandler(this);
myEventHandler = MediaFactory::createEventHandler(*this);
myEventHandler->initialize();
// Create a properties set for us to use and set it up
@ -238,7 +238,7 @@ void OSystem::saveConfig()
{
// Ask all subsystems to save their settings
if(myFrameBuffer)
myFrameBuffer->ntsc().saveConfig(*mySettings);
myFrameBuffer->tiaSurface().ntsc().saveConfig(*mySettings);
mySettings->saveConfig();
}
@ -352,7 +352,7 @@ FBInitStatus OSystem::createFrameBuffer()
void OSystem::createSound()
{
if(!mySound)
mySound = MediaFactory::createAudio(this);
mySound = MediaFactory::createAudio(*this);
#ifndef SOUND_SUPPORT
mySettings->setValue("sound", false);
#endif
@ -626,7 +626,7 @@ Console* OSystem::openConsole(const FilesystemNode& romfile, string& md5,
// Finally, create the cart with the correct properties
if(cart)
console = new Console(this, cart, props);
console = new Console(*this, *cart, props);
}
// Free the image since we don't need it any longer

View File

@ -34,7 +34,7 @@
#include "Settings.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Settings::Settings(OSystem* osystem)
Settings::Settings(OSystem& osystem)
: myOSystem(osystem)
{
// Video-related options
@ -165,10 +165,10 @@ void Settings::loadConfig()
string line, key, value;
string::size_type equalPos, garbage;
ifstream in(myOSystem->configFile().c_str());
ifstream in(myOSystem.configFile().c_str());
if(!in || !in.is_open())
{
myOSystem->logMessage("ERROR: Couldn't load settings file", 0);
myOSystem.logMessage("ERROR: Couldn't load settings file", 0);
return;
}
@ -236,7 +236,7 @@ string Settings::loadCommandLine(int argc, char** argv)
if(++i >= argc)
{
buf << "Missing argument for '" << key << "'" << endl;
myOSystem->logMessage(buf.str(), 0);
myOSystem.logMessage(buf.str(), 0);
return "";
}
string value = argv[i];
@ -257,7 +257,7 @@ string Settings::loadCommandLine(int argc, char** argv)
buf << "(E)\n";
}
myOSystem->logMessage(buf.str(), 2);
myOSystem.logMessage(buf.str(), 2);
}
else
return key;
@ -513,10 +513,10 @@ void Settings::saveConfig()
if(!settingsChanged)
return;
ofstream out(myOSystem->configFile().c_str());
ofstream out(myOSystem.configFile().c_str());
if(!out || !out.is_open())
{
myOSystem->logMessage("ERROR: Couldn't save settings file", 0);
myOSystem.logMessage("ERROR: Couldn't save settings file", 0);
return;
}
@ -674,7 +674,8 @@ int Settings::setExternal(const string& key, const Variant& value,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Settings::Settings(const Settings&)
Settings::Settings(const Settings& s)
: myOSystem(s.myOSystem)
{
}

View File

@ -40,7 +40,7 @@ class Settings
/**
Create a new settings abstract class
*/
Settings(OSystem* osystem);
Settings(OSystem& osystem);
/**
Destructor
@ -122,7 +122,7 @@ class Settings
protected:
// The parent OSystem object
OSystem* myOSystem;
OSystem& myOSystem;
// Structure used for storing settings
struct Setting

View File

@ -39,7 +39,7 @@ class Sound : public Serializable
Create a new sound object. The init method must be invoked before
using the object.
*/
Sound(OSystem* osystem) { myOSystem = osystem; }
Sound(OSystem& osystem) : myOSystem(osystem) { }
/**
Destructor
@ -129,7 +129,7 @@ class Sound : public Serializable
protected:
// The OSystem for this sound object
OSystem* myOSystem;
OSystem& myOSystem;
};
#endif

371
src/emucore/TIASurface.cxx Normal file
View File

@ -0,0 +1,371 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2014 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#include "FrameBuffer.hxx"
#include "Settings.hxx"
#include "OSystem.hxx"
#include "Console.hxx"
#include "TIA.hxx"
#include "TIASurface.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TIASurface::TIASurface(FrameBuffer& buffer, OSystem& system)
: myFB(buffer),
myOSystem(system),
myTIA(NULL),
myTiaSurface(NULL),
mySLineSurface(NULL),
myFilterType(kNormal),
myUsePhosphor(false),
myPhosphorBlend(77),
myScanlinesEnabled(false)
{
// Load NTSC filter settings
myNTSCFilter.loadConfig(myOSystem.settings());
// Create a surface for the TIA image and scanlines; we'll need them eventually
uInt32 tiaID = myFB.allocateSurface(ATARI_NTSC_OUT_WIDTH(160), 320);
myTiaSurface = myFB.surface(tiaID);
uInt32 scanID = myFB.allocateSurface(1, 320);
mySLineSurface = myFB.surface(scanID);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TIASurface::~TIASurface()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::initialize(const Console& console, const VideoMode& mode)
{
myTIA = &(console.tia());
#if 0
// FIX HERE ///////////////////////////////////
#if 0
bool enable = myProperties.get(Display_Phosphor) == "YES";
int blend = atoi(myProperties.get(Display_PPBlend).c_str());
myOSystem.frameBuffer().tiaSurface().enablePhosphor(enable, blend);
myOSystem.frameBuffer().tiaSurface().setNTSC(
(NTSCFilter::Preset)myOSystem.settings().getInt("tv.filter"), false);
#endif
// Grab the initial height before it's updated below
// We need it for the creating the TIA surface
uInt32 baseHeight = mode.image.height() / mode.zoom;
// The framebuffer only takes responsibility for TIA surfaces
// Other surfaces (such as the ones used for dialogs) are allocated
// in the Dialog class
if(inTIAMode)
{
// Since we have free hardware stretching, the base TIA surface is created
// only once, and its texture coordinates changed when we want to draw a
// smaller or larger image
if(!myTiaSurface)
myTiaSurface = new FBSurfaceTIA(*this);
myTiaSurface->updateCoords(baseHeight, mode.image.x(), mode.image.y(),
mode.image.width(), mode.image.height());
myTiaSurface->enableScanlines(ntscEnabled());
myTiaSurface->setTexInterpolation(myOSystem.settings().getBool("tia.inter"));
myTiaSurface->setScanIntensity(myOSystem.settings().getInt("tv.scanlines"));
myTiaSurface->setScanInterpolation(myOSystem.settings().getBool("tv.scaninter"));
myTiaSurface->setTIA(myOSystem.console().tia());
}
/////////////////////////////////////////////
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::setPalette(const uInt32* tia_palette, const uInt32* rgb_palette)
{
myPalette = tia_palette;
cerr << "TIASurface::setPalette\n";
for(int i = 0; i < 256; ++i)
cerr << myPalette[i] << " ";
cerr << endl;
// Set palette for phosphor effect
for(int i = 0; i < 256; ++i)
{
for(int j = 0; j < 256; ++j)
{
uInt8 ri = (rgb_palette[i] >> 16) & 0xff;
uInt8 gi = (rgb_palette[i] >> 8) & 0xff;
uInt8 bi = rgb_palette[i] & 0xff;
uInt8 rj = (rgb_palette[j] >> 16) & 0xff;
uInt8 gj = (rgb_palette[j] >> 8) & 0xff;
uInt8 bj = rgb_palette[j] & 0xff;
Uint8 r = (Uint8) getPhosphor(ri, rj);
Uint8 g = (Uint8) getPhosphor(gi, gj);
Uint8 b = (Uint8) getPhosphor(bi, bj);
myPhosphorPalette[i][j] = myFB.mapRGB(r, g, b);
}
}
// The NTSC filtering needs access to the raw RGB data, since it calculates
// its own internal palette
myNTSCFilter.setTIAPalette(*this, rgb_palette);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 TIASurface::pixel(uInt32 idx, uInt8 shift) const
{
uInt8 c = *(myTIA->currentFrameBuffer() + idx) | shift;
uInt8 p = *(myTIA->previousFrameBuffer() + idx) | shift;
return (!myUsePhosphor ? myPalette[c] : myPhosphorPalette[c][p]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::setNTSC(NTSCFilter::Preset preset, bool show)
{
ostringstream buf;
if(preset == NTSCFilter::PRESET_OFF)
{
enableNTSC(false);
buf << "TV filtering disabled";
}
else
{
enableNTSC(true);
const string& mode = myNTSCFilter.setPreset(preset);
buf << "TV filtering (" << mode << " mode)";
}
myOSystem.settings().setValue("tv.filter", (int)preset);
if(show) myFB.showMessage(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::setScanlineIntensity(int amount)
{
ostringstream buf;
if(ntscEnabled())
{
uInt32 intensity = enableScanlines(amount);
buf << "Scanline intensity at " << intensity << "%";
myOSystem.settings().setValue("tv.scanlines", intensity);
}
else
buf << "Scanlines only available in TV filtering mode";
myFB.showMessage(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::toggleScanlineInterpolation()
{
ostringstream buf;
if(ntscEnabled())
{
bool enable = !myOSystem.settings().getBool("tv.scaninter");
enableScanlineInterpolation(enable);
buf << "Scanline interpolation " << (enable ? "enabled" : "disabled");
myOSystem.settings().setValue("tv.scaninter", enable);
}
else
buf << "Scanlines only available in TV filtering mode";
myFB.showMessage(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 TIASurface::enableScanlines(int relative, int absolute)
{
uInt32& intensity = mySLineSurface->myAttributes.blendalpha;
if(relative == 0) intensity = absolute;
else intensity += relative;
intensity = BSPF_max(0u, intensity);
intensity = BSPF_min(100u, intensity);
mySLineSurface->applyAttributes();
//FIXSDL myRedrawEntireFrame = true;
return intensity;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::enableScanlineInterpolation(bool enable)
{
mySLineSurface->myAttributes.smoothing = enable;
mySLineSurface->applyAttributes();
//FIXSDL myRedrawEntireFrame = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::enablePhosphor(bool enable, int blend)
{
myUsePhosphor = enable;
myPhosphorBlend = blend;
myFilterType = FilterType(enable ? myFilterType | 0x01 : myFilterType & 0x10);
//FIXSDL myRedrawEntireFrame = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 TIASurface::getPhosphor(uInt8 c1, uInt8 c2) const
{
if(c2 > c1)
BSPF_swap(c1, c2);
return ((c1 - c2) * myPhosphorBlend)/100 + c2;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::enableNTSC(bool enable)
{
myFilterType = FilterType(enable ? myFilterType | 0x10 : myFilterType & 0x01);
// Normal vs NTSC mode uses different source widths
const GUI::Rect& src = myTiaSurface->srcRect();
myTiaSurface->setSrcSize(enable ? ATARI_NTSC_OUT_WIDTH(160) : 160, src.height());
myTiaSurface->myAttributes.smoothing =
myOSystem.settings().getBool("tia.inter");
myTiaSurface->applyAttributes();
myScanlinesEnabled = enable;
mySLineSurface->myAttributes.smoothing =
myOSystem.settings().getBool("tv.scaninter");
mySLineSurface->myAttributes.blendalpha =
myOSystem.settings().getInt("tv.scanlines");
mySLineSurface->applyAttributes();
//FIXSDL myRedrawEntireFrame = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string TIASurface::effectsInfo() const
{
ostringstream buf;
switch(myFilterType)
{
case kNormal:
buf << "Disabled, normal mode";
break;
case kPhosphor:
buf << "Disabled, phosphor mode";
break;
case kBlarggNormal:
buf << myNTSCFilter.getPreset() << ", scanlines="
<< mySLineSurface->myAttributes.blendalpha << "/"
<< (mySLineSurface->myAttributes.smoothing ? "inter" : "nointer");
break;
case kBlarggPhosphor:
buf << myNTSCFilter.getPreset() << ", phosphor, scanlines="
<< mySLineSurface->myAttributes.blendalpha << "/"
<< (mySLineSurface->myAttributes.smoothing ? "inter" : "nointer");
break;
}
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::render()
{
#if 0
cerr << "src: " << myTiaSurface->srcRect() << endl
<< "dst: " << myTiaSurface->dstRect() << endl
<< endl;
#endif
// Copy the mediasource framebuffer to the RGB texture
// In hardware rendering mode, it's faster to just assume that the screen
// is dirty and always do an update
uInt8* currentFrame = myTIA->currentFrameBuffer();
uInt8* previousFrame = myTIA->previousFrameBuffer();
uInt32 width = myTIA->width();
uInt32 height = myTIA->height();
uInt32 *buffer, pitch;
myTiaSurface->basePtr(buffer, pitch);
//cerr << "buffer=" << buffer << ", pitch=" << pitch << endl;
// TODO - Eventually 'phosphor' won't be a separate mode, and will become
// a post-processing filter by blending several frames.
switch(myFilterType)
{
case kNormal:
{
uInt32 bufofsY = 0;
uInt32 screenofsY = 0;
for(uInt32 y = 0; y < height; ++y)
{
uInt32 pos = screenofsY;
for(uInt32 x = 0; x < width; ++x)
buffer[pos++] = (uInt32) myPalette[currentFrame[bufofsY + x]];
bufofsY += width;
screenofsY += pitch;
}
break;
}
case kPhosphor:
{
uInt32 bufofsY = 0;
uInt32 screenofsY = 0;
for(uInt32 y = 0; y < height; ++y)
{
uInt32 pos = screenofsY;
for(uInt32 x = 0; x < width; ++x)
{
const uInt32 bufofs = bufofsY + x;
buffer[pos++] = (uInt32)
myPhosphorPalette[currentFrame[bufofs]][previousFrame[bufofs]];
}
bufofsY += width;
screenofsY += pitch;
}
break;
}
case kBlarggNormal:
{
myNTSCFilter.blit_single(currentFrame, width, height,
buffer, pitch);
break;
}
case kBlarggPhosphor:
{
myNTSCFilter.blit_double(currentFrame, previousFrame, width, height,
buffer, pitch);
break;
}
}
// Draw TIA image
myTiaSurface->render();
// Draw overlaying scanlines
if(myScanlinesEnabled)
mySLineSurface->render();
}

174
src/emucore/TIASurface.hxx Normal file
View File

@ -0,0 +1,174 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2014 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#ifndef TIASURFACE_HXX
#define TIASURFACE_HXX
class TIA;
class Console;
class OSystem;
class FrameBuffer;
class FBSurface;
class VideoMode;
#include "NTSCFilter.hxx"
#include "bspf.hxx"
/**
This class is basically a wrapper around all things related to rendering
the TIA image to FBSurface's, and presenting the results to the screen.
This is placed in a separate class since currently, rendering a TIA image
can consist of TV filters, a separate scanline surface, phosphor modes, etc.
@author Stephen Anthony
*/
class TIASurface
{
friend class FrameBuffer;
public:
/**
Creates a new TIASurface object
*/
TIASurface(FrameBuffer& buffer, OSystem& system);
/**
Destructor
*/
virtual ~TIASurface();
/**
Set the TIA object, which is needed for actually rendering the TIA image.
*/
void initialize(const Console& console, const VideoMode& mode);
/**
Set the palette for TIA rendering. This currently consists of two
components: the actual TIA palette, and a mixed TIA palette used
in phosphor mode. The latter may eventually disappear once a better
phosphor emulation is developed.
@param tia_palette An actual TIA palette, converted to data values
that are actually usable by the framebuffer
@param rgb_palette The RGB components of the palette, needed for
calculating a phosphor palette
*/
void setPalette(const uInt32* tia_palette, const uInt32* rgb_palette);
/**
Get the TIA pixel associated with the given TIA buffer index,
shifting by the given offset (for greyscale values).
*/
uInt32 pixel(uInt32 idx, uInt8 shift = 0) const;
/**
Get the NTSCFilter object associated with the framebuffer
*/
NTSCFilter& ntsc() { return myNTSCFilter; }
/**
Use NTSC filtering effects specified by the given preset.
*/
void setNTSC(NTSCFilter::Preset preset, bool show = true);
/**
Increase/decrease current scanline intensity by given relative amount.
*/
void setScanlineIntensity(int relative);
/**
Toggles interpolation/smoothing of scanlines in TV modes.
*/
void toggleScanlineInterpolation();
/**
Change scanline intensity and interpolation.
@param relative If non-zero, change current intensity by
'relative' amount, otherwise set to 'absolute'
@return New current intensity
*/
uInt32 enableScanlines(int relative, int absolute = 50);
void enableScanlineInterpolation(bool enable);
/**
Enable/disable phosphor effect.
*/
void enablePhosphor(bool enable, int blend);
/**
Used to calculate an averaged color for the 'phosphor' effect.
@param c1 Color 1
@param c2 Color 2
@return Averaged value of the two colors
*/
uInt8 getPhosphor(uInt8 c1, uInt8 c2) const;
/**
Enable/disable/query NTSC filtering effects.
*/
void enableNTSC(bool enable);
bool ntscEnabled() const { return myFilterType & 0x10; }
string effectsInfo() const;
/**
This method should be called to draw the TIA image(s) to the screen.
*/
void render();
private:
FrameBuffer& myFB;
OSystem& myOSystem;
TIA* myTIA;
FBSurface *myTiaSurface, *mySLineSurface;
// Enumeration created such that phosphor off/on is in LSB,
// and Blargg off/on is in MSB
enum FilterType {
kNormal = 0x00,
kPhosphor = 0x01,
kBlarggNormal = 0x10,
kBlarggPhosphor = 0x11
};
FilterType myFilterType;
// NTSC object to use in TIA rendering mode
NTSCFilter myNTSCFilter;
// Use phosphor effect (aka no flicker on 30Hz screens)
bool myUsePhosphor;
// Amount to blend when using phosphor effect
int myPhosphorBlend;
// Use scanlines in TIA rendering mode
bool myScanlinesEnabled;
// Palette for normal TIA rendering mode
const uInt32* myPalette;
// Palette for phosphor rendering mode
uInt32 myPhosphorPalette[256][256];
};
#endif

View File

@ -71,6 +71,7 @@ MODULE_OBJS := \
src/emucore/TIA.o \
src/emucore/TIASnd.o \
src/emucore/TIATables.o \
src/emucore/TIASurface.o \
src/emucore/TrackBall.o \
src/emucore/Thumbulator.o

View File

@ -463,7 +463,7 @@ void VideoDialog::saveConfig()
adj.artifacts = myTVArtifacts->getValue();
adj.fringing = myTVFringe->getValue();
adj.bleed = myTVBleed->getValue();
instance().frameBuffer().ntsc().setCustomAdjustables(adj);
instance().frameBuffer().tiaSurface().ntsc().setCustomAdjustables(adj);
// TV scanline intensity and interpolation
instance().settings().setValue("tv.scanlines", myTVScanIntenseLabel->getLabel());
@ -565,7 +565,8 @@ void VideoDialog::handleTVModeChange(NTSCFilter::Preset preset)
void VideoDialog::loadTVAdjustables(NTSCFilter::Preset preset)
{
NTSCFilter::Adjustable adj;
instance().frameBuffer().ntsc().getAdjustables(adj, (NTSCFilter::Preset)preset);
instance().frameBuffer().tiaSurface().ntsc().getAdjustables(
adj, (NTSCFilter::Preset)preset);
myTVSharp->setValue(adj.sharpness);
myTVSharpLabel->setValue(adj.sharpness);
myTVHue->setValue(adj.hue);

View File

@ -26,7 +26,7 @@ extern "C" {
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SettingsMACOSX::SettingsMACOSX(OSystem* osystem)
SettingsMACOSX::SettingsMACOSX(OSystem& osystem)
: Settings(osystem)
{
}

View File

@ -36,7 +36,7 @@ class SettingsMACOSX : public Settings
/**
Create a new UNIX settings object
*/
SettingsMACOSX(OSystem* osystem);
SettingsMACOSX(OSystem& osystem);
/**
Destructor

View File

@ -20,7 +20,7 @@
#include "SettingsUNIX.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SettingsUNIX::SettingsUNIX(OSystem* osystem)
SettingsUNIX::SettingsUNIX(OSystem& osystem)
: Settings(osystem)
{
}

View File

@ -36,7 +36,7 @@ class SettingsUNIX : public Settings
/**
Create a new UNIX settings object
*/
SettingsUNIX(OSystem* osystem);
SettingsUNIX(OSystem& osystem);
/**
Destructor

View File

@ -20,7 +20,7 @@
#include "SettingsWINDOWS.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SettingsWINDOWS::SettingsWINDOWS(OSystem* osystem)
SettingsWINDOWS::SettingsWINDOWS(OSystem& osystem)
: Settings(osystem)
{
setInternal("fragsize", "1024");

View File

@ -30,7 +30,7 @@ class SettingsWINDOWS : public Settings
/**
Create a new UNIX settings object
*/
SettingsWINDOWS(OSystem* osystem);
SettingsWINDOWS(OSystem& osystem);
/**
Destructor