diff --git a/Changes.txt b/Changes.txt index 728cb23e1..ffaa92033 100644 --- a/Changes.txt +++ b/Changes.txt @@ -14,8 +14,13 @@ 3.7 to 3.7.1: (xxxx xx, 2012) + * Improved TIA emulation with ROMs that have too few or too many + scanlines; the output is now blanked as on a real TV. Special thanks + to Omegamatrix of AtariAge for test ROMs in this area. + * Fixed several bugs in DPC+ bankswitching scheme, including ability to - load and save state files. + load and save state files. As well, ROMs now work correctly after + console format autodetection. -Have fun! diff --git a/src/common/FBSurfaceTIA.cxx b/src/common/FBSurfaceTIA.cxx index 5b8d447ee..8ecfeec25 100644 --- a/src/common/FBSurfaceTIA.cxx +++ b/src/common/FBSurfaceTIA.cxx @@ -199,6 +199,12 @@ void FBSurfaceTIA::update() myFB.myDirtyFlag = true; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FBSurfaceTIA::invalidate() +{ + SDL_FillRect(myTexture, NULL, 0); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FBSurfaceTIA::free() { diff --git a/src/common/FBSurfaceTIA.hxx b/src/common/FBSurfaceTIA.hxx index 95c3ba1e6..6d4addc4c 100644 --- a/src/common/FBSurfaceTIA.hxx +++ b/src/common/FBSurfaceTIA.hxx @@ -50,6 +50,7 @@ class FBSurfaceTIA : public FBSurface uInt32 getHeight() const { return myImageH; } void translateCoords(Int32& x, Int32& y) const; void update(); + void invalidate(); void free(); void reload(); diff --git a/src/common/FrameBufferGL.cxx b/src/common/FrameBufferGL.cxx index 7b89700e6..3b981ce29 100644 --- a/src/common/FrameBufferGL.cxx +++ b/src/common/FrameBufferGL.cxx @@ -332,6 +332,8 @@ bool FrameBufferGL::setVidMode(VideoMode& mode) void FrameBufferGL::invalidate() { p_gl.Clear(GL_COLOR_BUFFER_BIT); + if(myTiaSurface) + myTiaSurface->invalidate(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/FrameBuffer.hxx b/src/emucore/FrameBuffer.hxx index a3c610ef2..06f7807a0 100644 --- a/src/emucore/FrameBuffer.hxx +++ b/src/emucore/FrameBuffer.hxx @@ -812,6 +812,12 @@ class FBSurface */ virtual void update() { } + /** + This method should be called to reset the surface to empty + pixels / colour black. + */ + virtual void invalidate() { } + /** This method should be called to free any resources being used by the surface. diff --git a/src/emucore/TIA.cxx b/src/emucore/TIA.cxx index 839976e1e..8a900bcad 100644 --- a/src/emucore/TIA.cxx +++ b/src/emucore/TIA.cxx @@ -46,7 +46,6 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings) : myConsole(console), mySound(sound), mySettings(settings), - myFrameWidth(160), myFrameYStart(34), myFrameHeight(210), myMaximumNumberOfScanlines(262), @@ -194,8 +193,7 @@ void TIA::frameReset() // Calculate color clock offsets for starting and stopping frame drawing // Note that although we always start drawing at scanline zero, the // framebuffer that is exposed outside the class actually starts at 'ystart' - myFramePointerOffset = myFrameWidth * myFrameYStart; - myStartDisplayOffset = 0; + myFramePointerOffset = 160 * myFrameYStart; // NTSC screens will process at least 262 scanlines, // while PAL will have at least 312 @@ -209,7 +207,7 @@ void TIA::frameReset() // Reasonable values to start and stop the current frame drawing myClockWhenFrameStarted = mySystem->cycles() * 3; - myClockStartDisplay = myClockWhenFrameStarted + myStartDisplayOffset; + myClockStartDisplay = myClockWhenFrameStarted; myClockStopDisplay = myClockWhenFrameStarted + myStopDisplayOffset; myClockAtLastUpdate = myClockWhenFrameStarted; myClocksToEndOfScanLine = 228; @@ -558,7 +556,7 @@ inline void TIA::startFrame() // Setup clocks that'll be used for drawing this frame myClockWhenFrameStarted = -1 * clocks; - myClockStartDisplay = myClockWhenFrameStarted + myStartDisplayOffset; + myClockStartDisplay = myClockWhenFrameStarted; myClockStopDisplay = myClockWhenFrameStarted + myStopDisplayOffset; myClockAtLastUpdate = myClockStartDisplay; myClocksToEndOfScanLine = 228; @@ -622,22 +620,32 @@ inline void TIA::endFrame() myStopDisplayOffset = offset; } - // This is a bit of a hack for those ROMs which generate too many - // scanlines each frame, usually caused by VBLANK taking too long - // When this happens, the frame pointers sometimes get 'confused', - // and the framebuffer class doesn't properly overwrite data from - // the previous frame, causing graphical garbage - // - // We basically erase the entire contents of both buffers, making - // sure that they're also different from one another - // This will force the framebuffer class to completely re-render - // the screen - if(previousCount > myMaximumNumberOfScanlines && - myScanlineCountForLastFrame <= myMaximumNumberOfScanlines) + // The following handle cases where scanlines either go too high or too + // low compared to the previous frame, in which case certain portions + // of the framebuffer are cleared to zero (black pixels) + // Due to the FrameBuffer class (potentially) doing dirty-rectangle + // updates, each internal buffer must be set slightly differently, + // otherwise they won't know anything has changed + // Hence, the front buffer is set to pixel 0, and the back to pixel 1 + + // Did we generate too many scanlines? + // (usually caused by VBLANK taking too long) + // If so, blank entire viewable area + if(myScanlineCountForLastFrame > 342 && previousCount <= 342) { memset(myCurrentFrameBuffer, 0, 160 * 320); memset(myPreviousFrameBuffer, 1, 160 * 320); } + // Did the number of scanlines decrease? + // If so, blank scanlines that weren't rendered this frame + else if(myScanlineCountForLastFrame < previousCount && + myScanlineCountForLastFrame < 320 && previousCount < 320) + { + uInt32 offset = myScanlineCountForLastFrame * 160, + stride = (previousCount - myScanlineCountForLastFrame) * 160; + memset(myCurrentFrameBuffer + offset, 0, stride); + memset(myPreviousFrameBuffer + offset, 1, stride); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/TIA.hxx b/src/emucore/TIA.hxx index b44da279b..ef30a94f8 100644 --- a/src/emucore/TIA.hxx +++ b/src/emucore/TIA.hxx @@ -188,9 +188,9 @@ class TIA : public Device /** Answers the width and height of the frame buffer */ - uInt32 width() const { return myFrameWidth; } - uInt32 height() const { return myFrameHeight; } - uInt32 ystart() const { return myFrameYStart; } + inline uInt32 width() const { return 160; } + inline uInt32 height() const { return myFrameHeight; } + inline uInt32 ystart() const { return myFrameYStart; } /** Changes the current Height/YStart properties. @@ -403,18 +403,12 @@ class TIA : public Device // (this is used when loading state files with a 'partial' frame) uInt32 myFramePointerClocks; - // Indicates the width of the visible scanline - uInt32 myFrameWidth; - // Indicated what scanline the frame should start being drawn at uInt32 myFrameYStart; // Indicates the height of the frame in scanlines uInt32 myFrameHeight; - // Indicates offset in color clocks when display should begin - uInt32 myStartDisplayOffset; - // Indicates offset in color clocks when display should stop uInt32 myStopDisplayOffset;